Compare commits
6064 commits
Author | SHA1 | Date | |
---|---|---|---|
|
96f5d1ca87 | ||
|
7cb7887234 | ||
|
4728739597 | ||
|
fc0d58ff48 | ||
|
491e260d20 | ||
|
a132733b2d | ||
|
b377dbb96f | ||
|
c4d753c931 | ||
|
ee3b7c5da5 | ||
|
dcc267f6f4 | ||
|
ccf60fc9ca | ||
|
a38a3e7ddf | ||
|
beb4aa52ea | ||
|
f7d0fb9ab2 | ||
|
ff331f4eba | ||
|
94eae6a8dc | ||
|
f8d6b54dbb | ||
|
67c4f2d95e | ||
|
03fefa8933 | ||
|
c8ec77a734 | ||
|
4f32f94a51 | ||
|
3dc384a17a | ||
|
f1d0d1a9fe | ||
|
c036a7d871 | ||
|
6e63f3d2b4 | ||
|
09748e80e9 | ||
|
44a4f356ba | ||
|
a0f41bf82a | ||
|
5ae3e2818b | ||
|
1a0b81ac64 | ||
|
20d99886ca | ||
|
b9fe301036 | ||
|
b5844018f2 | ||
|
30508502d3 | ||
|
bca601d377 | ||
|
65191375b8 | ||
|
a534eb45ce | ||
|
e796f08184 | ||
|
ed38d8d3a1 | ||
|
07ad5ecfce | ||
|
4db5e663c3 | ||
|
529faeea9e | ||
|
47510899c7 | ||
|
4cd949c7e1 | ||
|
31d7e64073 | ||
|
7c1ee142dd | ||
|
25e86c5ca9 | ||
|
c41dd92007 | ||
|
a564d89d46 | ||
|
6c6a6e85da | ||
|
ed0acd8027 | ||
|
b9a690463d | ||
|
cbf4586c4c | ||
|
c3986957c4 | ||
|
8795cf6494 | ||
|
80af8a5e79 | ||
|
b60f65c1e8 | ||
|
943107115a | ||
|
ddbe9956e4 | ||
|
fdbcce3a5e | ||
|
f007c77641 | ||
|
9439487219 | ||
|
df6da52195 | ||
|
6ca89c80af | ||
|
7fe0b87d83 | ||
|
8a654b6955 | ||
|
5a8cf824f6 | ||
|
5c25b57989 | ||
|
5d1fe64bc8 | ||
|
a731e25778 | ||
|
0d6dc08578 | ||
|
40261fdf14 | ||
|
590b4aa240 | ||
|
2a696ddb34 | ||
|
d7f08d1b0c | ||
|
4aa1ef28ea | ||
|
58faef6ff6 | ||
|
34a52a7028 | ||
|
ce751cb89d | ||
|
5cf2883444 | ||
|
6bff338bad | ||
|
c78862052c | ||
|
1f54cef71c | ||
|
d00508105b | ||
|
c272421910 | ||
|
78624c5bcb | ||
|
c681435432 | ||
|
4d3f637684 | ||
|
5e14398af4 | ||
|
990f87acc8 | ||
|
eeb376460d | ||
|
ef707b3461 | ||
|
2af918132e | ||
|
b9b654714e | ||
|
fe399e0e0c | ||
|
b192053e28 | ||
|
a84271aa7e | ||
|
1901b512d2 | ||
|
9fdda7eca8 | ||
|
a68ed897f0 | ||
|
582ff96d19 | ||
|
0374a55eb3 | ||
|
ccbe38f78c | ||
|
958840da89 | ||
|
1530411218 | ||
|
e5ec0f18c0 | ||
|
0f44e8c812 | ||
|
1cc0f3c8c9 | ||
|
d9c39c274e | ||
|
c38fb866b7 | ||
|
5ad1d9db5e | ||
|
32f3d92d6b | ||
|
72b45eec2e | ||
|
23716b0eff | ||
|
859df84b45 | ||
|
131bd933a6 | ||
|
52904ee6ad | ||
|
e3339fe3d8 | ||
|
547ef747da | ||
|
63b27ea067 | ||
|
bc5881b70a | ||
|
f4b95d42a6 | ||
|
ef76a578a4 | ||
|
3b99d24ceb | ||
|
4701abff4c | ||
|
717b8daafe | ||
|
c346e46022 | ||
|
24632ae81b | ||
|
befde271eb | ||
|
d689f57c94 | ||
|
ad3f503c0c | ||
|
ae6c780af6 | ||
|
8b9cd3959a | ||
|
dffeab320e | ||
|
999586a110 | ||
|
f8d5487f8e | ||
|
4189008245 | ||
|
44115d7d7a | ||
|
841e2f44c0 | ||
|
a8e4984cf7 | ||
|
49196c2ec4 | ||
|
3646dc0bd2 | ||
|
694de1d67b | ||
|
31caab5f92 | ||
|
472996c8b3 | ||
|
d62c67a5f5 | ||
|
e486151aea | ||
|
9c407e667d | ||
|
18efdc2c51 | ||
|
6dff39344b | ||
|
c4de3df492 | ||
|
f2e11f088b | ||
|
782f0511b9 | ||
|
fa093ee609 | ||
|
612bcc4bb8 | ||
|
4ad67acedd | ||
|
467dc19cbd | ||
|
726711513f | ||
|
9468642269 | ||
|
d387d4811f | ||
|
1b3c2dab2e | ||
|
76573bf293 | ||
|
5d3326b93f | ||
|
68dac4e181 | ||
|
262c96ec0b | ||
|
2acdc33aa1 | ||
|
8acd33d0df | ||
|
a2e23c1a71 | ||
|
1b5cc175b9 | ||
|
a71da25b57 | ||
|
5ac614f97d | ||
|
b8b8b82ff4 | ||
|
7da3dbcb39 | ||
|
680293e79c | ||
|
023b16349e | ||
|
c4976437a8 | ||
|
97ca2f3c78 | ||
|
e76385e7cd | ||
|
7c2fb227f4 | ||
|
08bfa0b18f | ||
|
952cad8d63 | ||
|
5bce39abf8 | ||
|
fc57c0b27e | ||
|
dd4bc5fbfe | ||
|
d2a7434c67 | ||
|
5fa885b150 | ||
|
f3fb758f0c | ||
|
6386ec029c | ||
|
ad7cefa352 | ||
|
09d9bc910e | ||
|
e2f1f8d69d | ||
|
be2bfd867c | ||
|
133a7a0e1b | ||
|
efb47edb9f | ||
|
36bec19a84 | ||
|
6db6c8678c | ||
|
5603f9f374 | ||
|
7ebb8c3f2e | ||
|
acb6f243fd | ||
|
220f149299 | ||
|
1baabb3c05 | ||
|
617b17ad46 | ||
|
8af86e4c1e | ||
|
9dc9a670a5 | ||
|
b46ddf35fc | ||
|
de762400ad | ||
|
e60ece2b5e | ||
|
e6976a54e1 | ||
|
64daaf1887 | ||
|
1c75ec9ec1 | ||
|
c8a61ec98c | ||
|
aeeae76750 | ||
|
30b062fd43 | ||
|
8f899a1101 | ||
|
386c739d5b | ||
|
fddff783c8 | ||
|
bbd1161147 | ||
|
ab938602a9 | ||
|
e31890806c | ||
|
30c77ea4c1 | ||
|
175cdba9b1 | ||
|
ea29cd0890 | ||
|
68653c31c0 | ||
|
be5fdab3aa | ||
|
f4daf5856e | ||
|
49d869f662 | ||
|
b36bb9115a | ||
|
9ad2d24ad8 | ||
|
0088fe0ab7 | ||
|
ab93b17a7e | ||
|
9f1b980844 | ||
|
86d05ac180 | ||
|
bf6fcf6347 | ||
|
b9e4e27195 | ||
|
8585134db4 | ||
|
7e862939db | ||
|
0d3bd69a17 | ||
|
2b97b661d8 | ||
|
24f12b024d | ||
|
f7d363dc96 | ||
|
47050003a0 | ||
|
4df6e35270 | ||
|
307f598bc8 | ||
|
eb10249a75 | ||
|
b4318e9967 | ||
|
c53561c9a0 | ||
|
f2f9f1d377 | ||
|
4487a374b1 | ||
|
06f8368ce6 | ||
|
5b976a8d80 | ||
|
e73803c72c | ||
|
b3876142d2 | ||
|
9f11946f8a | ||
|
9c28f61dbd | ||
|
09291bbdd2 | ||
|
7fa6314791 | ||
|
65d95d767a | ||
|
8306adb102 | ||
|
4b3db07cdb | ||
|
c24a3a3b15 | ||
|
aca6be3adf | ||
|
9617532561 | ||
|
ff5e487e32 | ||
|
9c51ac5157 | ||
|
07eab539a6 | ||
|
a608a048ad | ||
|
0cfa03fa8a | ||
|
6525461d97 | ||
|
f592fa1235 | ||
|
2e1863af78 | ||
|
2a282711df | ||
|
91073d7379 | ||
|
3ce5458f32 | ||
|
98c194735c | ||
|
626ea64f66 | ||
|
0d32c0d92b | ||
|
ce04fdde72 | ||
|
4ed3c85a88 | ||
|
14063b023c | ||
|
3d32f0e953 | ||
|
d821bed2ea | ||
|
058e05df41 | ||
|
a7ba7cdcd5 | ||
|
c01656b1e3 | ||
|
5071529a74 | ||
|
6d543b830a | ||
|
e6154998fd | ||
|
01c6239043 | ||
|
4607ac2e93 | ||
|
9ca5632582 | ||
|
51195212b4 | ||
|
7414409aa0 | ||
|
adfd77f11d | ||
|
f3ea8cf45e | ||
|
3bb9542606 | ||
|
1d0b3829ed | ||
|
a5d7178bf8 | ||
|
cbef8ea407 | ||
|
2ff4ae1f08 | ||
|
edf7f53f76 | ||
|
f58816c33c | ||
|
1562a9c2ec | ||
|
6cd243f14e | ||
|
4b03f6c20f | ||
|
d0a2ba37e8 | ||
|
e8ccbebd6f | ||
|
d4de9d096f | ||
|
e1f06dd406 | ||
|
6f82cf12f5 | ||
|
ca8080a695 | ||
|
55d14090d0 | ||
|
da8498bb6f | ||
|
b33896844e | ||
|
ca212c08de | ||
|
784439dccf | ||
|
d818c1c6d9 | ||
|
b9384ad913 | ||
|
76b0cbcb4e | ||
|
6bf3306401 | ||
|
bf477c24d3 | ||
|
79f6cd774a | ||
|
c3c9a42502 | ||
|
4a92b7221a | ||
|
9d5d945bdb | ||
|
475ce05979 | ||
|
57d7029317 | ||
|
e4fe679916 | ||
|
123632f5ed | ||
|
56d83c931b | ||
|
a22ae6143a | ||
|
a1ec0571b2 | ||
|
2db39d4856 | ||
|
e7729daefc | ||
|
97b4d79ed5 | ||
|
890fad389d | ||
|
0c203ece2d | ||
|
9e7f89d2a2 | ||
|
24c8ba832a | ||
|
c2700266b0 | ||
|
2cd8c51a07 | ||
|
589823bdc1 | ||
|
5dc8be9aa2 | ||
|
fad296616c | ||
|
ec01b40e85 | ||
|
2de5c4821c | ||
|
9efe145688 | ||
|
51bc64fb35 | ||
|
6380483e8b | ||
|
ae1dcb031f | ||
|
9535a41187 | ||
|
47495c336b | ||
|
d69d4a8303 | ||
|
ab4d590547 | ||
|
85271fc2e5 | ||
|
f6159c5677 | ||
|
668b9b026c | ||
|
77de7cb785 | ||
|
e5d6c042a9 | ||
|
3ae397019c | ||
|
7d3e59cf2e | ||
|
4eb83bb7f6 | ||
|
1429ba9a07 | ||
|
889454f2bc | ||
|
2fba94c5e5 | ||
|
4726a110fc | ||
|
6b43d6aff2 | ||
|
024a3ee551 | ||
|
cd7381d8de | ||
|
f53764f949 | ||
|
57c3aa4560 | ||
|
bb530da5c2 | ||
|
cc6cbfbe71 | ||
|
6f556f5451 | ||
|
9074bd297b | ||
|
8030e6f76c | ||
|
27bd7fd737 | ||
|
77f436fa39 | ||
|
814760ba25 | ||
|
14c0f368b6 | ||
|
0761659a43 | ||
|
a4f752fb02 | ||
|
b2346cdaec | ||
|
01ca7293f5 | ||
|
4dfce51ded | ||
|
f82ed24c03 | ||
|
1f65e6d3b5 | ||
|
9bf7aaf6cd | ||
|
5512465b34 | ||
|
2f30ab558a | ||
|
5c136ae3af | ||
|
c927da00e0 | ||
|
1600fd9082 | ||
|
14acd124bc | ||
|
e3cbbfb9ed | ||
|
5f21e0b58b | ||
|
d22204a59f | ||
|
90289b8502 | ||
|
78aacee21b | ||
|
f47aca3558 | ||
|
73fc70dbe8 | ||
|
dc2a18e436 | ||
|
82590eb087 | ||
|
4c97ce747c | ||
|
ebbc5ed0ce | ||
|
dc1af5a9c5 | ||
|
85bd1eea27 | ||
|
2b151c6aa2 | ||
|
93fe3e06ef | ||
|
9d3a894991 | ||
|
0e6b727e53 | ||
|
e42a01f203 | ||
|
a28b58dbd0 | ||
|
a26a9ee14f | ||
|
c09fcd4f92 | ||
|
593359ec77 | ||
|
34ec4d5d40 | ||
|
3d8f3bc0b7 | ||
|
eea7bb7692 | ||
|
3a89e31dee | ||
|
0c504e4984 | ||
|
0bf070c33b | ||
|
dc8ad78206 | ||
|
48e938660d | ||
|
632d457f78 | ||
|
569a319ff5 | ||
|
47812ec002 | ||
|
c27dee57ea | ||
|
b289f533b3 | ||
|
3eb0a4071a | ||
|
5684610a55 | ||
|
f26f544ff6 | ||
|
b9e5b0cb53 | ||
|
13443b05a6 | ||
|
e70c00a0fe | ||
|
bb67b654c5 | ||
|
aef25819bc | ||
|
1d96f465f4 | ||
|
8f618ab408 | ||
|
5296d7ef9c | ||
|
b715500b48 | ||
|
37a5271f5a | ||
|
42fc71fafa | ||
|
02b6e4833a | ||
|
323a111362 | ||
|
e7df4d3dd9 | ||
|
3e52a0db95 | ||
|
94484873d1 | ||
|
0d6ea85167 | ||
|
674ec92224 | ||
|
e7e5037a86 | ||
|
fbcf426240 | ||
|
2301554e98 | ||
|
5bc35002ba | ||
|
9143810a4d | ||
|
8f118fb619 | ||
|
1113460b68 | ||
|
74c7e009b7 | ||
|
c20ab7d987 | ||
|
fe66121287 | ||
|
9605bbaa67 | ||
|
b7ce6a9f79 | ||
|
c04a73c11a | ||
|
f184725c5f | ||
|
26a0b0f1e8 | ||
|
fa1d222eee | ||
|
56cf163a23 | ||
|
afcedf6d77 | ||
|
21fc197ee0 | ||
|
fcb4c8fb61 | ||
|
b6e2c56ae6 | ||
|
b005985d4e | ||
|
1294fd5730 | ||
|
835fd86a08 | ||
|
b7004d72c5 | ||
|
eb566ca626 | ||
|
aa12f1c56b | ||
|
6cc5b38a2e | ||
|
e6c4330e4e | ||
|
1e827f9807 | ||
|
a4f26dc8f3 | ||
|
3f065918d9 | ||
|
2c2d4513ac | ||
|
937e64d296 | ||
|
3261d26181 | ||
|
c98a0a448f | ||
|
7e7218f5ce | ||
|
45262da726 | ||
|
aef5f1e139 | ||
|
3d4baea01c | ||
|
30306d6ec7 | ||
|
d7254eead6 | ||
|
9dced7133c | ||
|
c2fb1a0747 | ||
|
00a4d2d3c4 | ||
|
424ef3b3f9 | ||
|
996ef98b87 | ||
|
19d5a1c7c3 | ||
|
0481dd946f | ||
|
29109575f5 | ||
|
3782573ede | ||
|
bba91a7524 | ||
|
b67cadf743 | ||
|
56dda4392c | ||
|
34fec09ff1 | ||
|
cefd1339fc | ||
|
b915376194 | ||
|
455cc6ff75 | ||
|
cc9c376d0f | ||
|
018611f829 | ||
|
1781eab21f | ||
|
78b05d0ffc | ||
|
1c0df78278 | ||
|
6cc9da6b0a | ||
|
6af9cae0a5 | ||
|
ef29455652 | ||
|
503ab0f722 | ||
|
90883e76af | ||
|
113de8381c | ||
|
652f2edbe1 | ||
|
a67e36703f | ||
|
73c6943402 | ||
|
d46817d690 | ||
|
97cb64c62d | ||
|
3f70241fb7 | ||
|
21b71b38a3 | ||
|
b2f9442aba | ||
|
fa9f85c7e9 | ||
|
ffa285c2e7 | ||
|
7b1dc600d5 | ||
|
5e67ebeb9e | ||
|
af7066d33c | ||
|
dd2d95ecdf | ||
|
a86d9bd8e8 | ||
|
21b1516d80 | ||
|
4c15038194 | ||
|
538f9df5cc | ||
|
efb0412b63 | ||
|
5a486a5cca | ||
|
394857b5ce | ||
|
5043517cfb | ||
|
307d122a84 | ||
|
d444a2fb83 | ||
|
fb7c56e3d3 | ||
|
2b79be68e7 | ||
|
512d5e3348 | ||
|
4b6892ece9 | ||
|
5a49ac52f9 | ||
|
db1e30e4fc | ||
|
b4a61370c8 | ||
|
58b2f39ce5 | ||
|
56d882abed | ||
|
39acb2b84d | ||
|
3ccba08983 | ||
|
632aa764e6 | ||
|
f6342b6cf4 | ||
|
471585dcd5 | ||
|
51821a811f | ||
|
299a9ae7ba | ||
|
bf7a506f79 | ||
|
2e925f82ef | ||
|
ddef7e1139 | ||
|
672e47a7eb | ||
|
3e8e64a3e5 | ||
|
b554246502 | ||
|
6d683c98a3 | ||
|
ee079f4740 | ||
|
a090038d02 | ||
|
4f1499bd23 | ||
|
36393d77d3 | ||
|
e053ee4272 | ||
|
1d46c07307 | ||
|
f9b5e448c1 | ||
|
3effb008c9 | ||
|
a088f492f4 | ||
|
e9c8913248 | ||
|
b9a27c91da | ||
|
d4f654275b | ||
|
f6eb4c749d | ||
|
418fc00718 | ||
|
2537177929 | ||
|
9af719bf99 | ||
|
9e020b252e | ||
|
cc45e365ae | ||
|
97c667f67c | ||
|
063fc525b1 | ||
|
0f73d87509 | ||
|
402e85ad6e | ||
|
1d635e04e4 | ||
|
98d5d0cdd5 | ||
|
31d4a38f09 | ||
|
1ebe456f2d | ||
|
c6e5314fab | ||
|
a6a79883b7 | ||
|
b02e68222f | ||
|
da8522af64 | ||
|
84b93090a8 | ||
|
5695c892d0 | ||
|
696101a910 | ||
|
54dfe73d24 | ||
|
87928baa31 | ||
|
6a4fd33a03 | ||
|
790448f48b | ||
|
7759494c85 | ||
|
aed187e56c | ||
|
eac799f589 | ||
|
5ecb07b59a | ||
|
ff621fb7f1 | ||
|
958bca8800 | ||
|
eacd55fbca | ||
|
0e2ab5c273 | ||
|
c47634290e | ||
|
92d612c3e0 | ||
|
2bbe5732b7 | ||
|
e6e7fbc25f | ||
|
7d4d554436 | ||
|
d31db847b7 | ||
|
3562d3378b | ||
|
ababcd5481 | ||
|
7caffde0b6 | ||
|
c40b43de01 | ||
|
b0eb5650da | ||
|
52f221f976 | ||
|
26a5948d2a | ||
|
d86a3b962c | ||
|
d64b341b38 | ||
|
d580014c66 | ||
|
be9a1f80c1 | ||
|
73ff3b0d3b | ||
|
9fce9ca42a | ||
|
f1adb734e3 | ||
|
575e0ca457 | ||
|
69f088bb82 | ||
|
ef34f5fe7d | ||
|
e88aa7c96b | ||
|
38d129a0b6 | ||
|
392815d97c | ||
|
6e2e61012a | ||
|
e791089466 | ||
|
418f12f62a | ||
|
caff539ccd | ||
|
c0d1bb1a5c | ||
|
ea44d64511 | ||
|
1a69f8c3ad | ||
|
ccd3180a69 | ||
|
01dcbc18ac | ||
|
7c67ec4976 | ||
|
43d128362f | ||
|
1337c9c244 | ||
|
86953b2ac4 | ||
|
135c9b29a7 | ||
|
e0d67367ed | ||
|
d007132655 | ||
|
cfd9873bbc | ||
|
b2b95cc8f9 | ||
|
73c889eb10 | ||
|
642725efe7 | ||
|
29aafff2ce | ||
|
df425ac143 | ||
|
57a1d18db3 | ||
|
aa4a3d7afd | ||
|
06ad5525b8 | ||
|
f80fd24a55 | ||
|
51bd9bee0d | ||
|
52266406f8 | ||
|
cd601c77c7 | ||
|
6abae713f7 | ||
|
1312f92a8d | ||
|
92abf26d29 | ||
|
c11e4ba9a7 | ||
|
7ae00947f5 | ||
|
59f62473c9 | ||
|
8fbd08d027 | ||
|
dda557ed23 | ||
|
cb54eb40ce | ||
|
3eab1129b9 | ||
|
24f1402a14 | ||
|
bf00550388 | ||
|
78c83a8f26 | ||
|
e72f8e0412 | ||
|
6136fa7c49 | ||
|
8d2b4ed4a9 | ||
|
9e9b177674 | ||
|
4c4c83f0a1 | ||
|
0e98814732 | ||
|
92f25bf267 | ||
|
63a53c79d0 | ||
|
2f9a8c04dc | ||
|
8c67f42689 | ||
|
783a51e9ac | ||
|
841c61aaa1 | ||
|
157942a462 | ||
|
e88a27790c | ||
|
ed3932b7d5 | ||
|
2b5c185826 | ||
|
996ecca78b | ||
|
c3c128352f | ||
|
02a89543d6 | ||
|
c1954ff918 | ||
|
b49ae8c21d | ||
|
1a7b4435f3 | ||
|
ff5ca5f7f8 | ||
|
db0e458217 | ||
|
f01f7c54aa | ||
|
c59407f105 | ||
|
fdc5d7458f | ||
|
6aafb9b2d4 | ||
|
aa9ad1ed60 | ||
|
aa9b8453a0 | ||
|
4daa824b3c | ||
|
4f2e4524b8 | ||
|
8ac510e4d6 | ||
|
4f27c763af | ||
|
0e969c0b72 | ||
|
b396801e28 | ||
|
682c8a59c2 | ||
|
5a25de37ef | ||
|
bdb923df4a | ||
|
4ef2cf4c28 | ||
|
990ca38d21 | ||
|
c7e430573f | ||
|
a328b64464 | ||
|
a16d427536 | ||
|
c98a07825b | ||
|
a98ca6fcf3 | ||
|
4550f8c50f | ||
|
9afca43807 | ||
|
27ab364df5 | ||
|
615216f397 | ||
|
46b1b7ab34 | ||
|
30d9882851 | ||
|
dfdebda0b6 | ||
|
9d8a83314b | ||
|
e19ce27352 | ||
|
4d711691d0 | ||
|
ee0f1e9d58 | ||
|
a24162f596 | ||
|
e82443241b | ||
|
9f052702e5 | ||
|
b38382a68f | ||
|
785324827c | ||
|
31c7b6747b | ||
|
dc767c14b9 | ||
|
30ec03259d | ||
|
38c12288f1 | ||
|
0e22a90579 | ||
|
0cdf75d41a | ||
|
3c6fa6e583 | ||
|
ee882fa462 | ||
|
3431ed9857 | ||
|
279808b44e | ||
|
2fd529a993 | ||
|
1f6f79c91e | ||
|
52ee5d0fff | ||
|
2f44b40d68 | ||
|
20157254c3 | ||
|
09c17ba581 | ||
|
a5f88e14d0 | ||
|
e78bda65fe | ||
|
3ea496013f | ||
|
7e1873d927 | ||
|
fe0810aff9 | ||
|
e35a87e3eb | ||
|
a6fcf2e066 | ||
|
25316825b1 | ||
|
c74e1c9db3 | ||
|
be9de6b9d9 | ||
|
fe8c843cc8 | ||
|
f48ae18630 | ||
|
83e0b786d4 | ||
|
acd5185ad4 | ||
|
0263c649f4 | ||
|
8176e9155b | ||
|
424163c7d3 | ||
|
2c87170ccf | ||
|
02322c46de | ||
|
28b5281c45 | ||
|
4d79a55904 | ||
|
027cbefb87 | ||
|
a08d82d94e | ||
|
5f1456337b | ||
|
6eeb4883af | ||
|
b5a5478a8a | ||
|
0d0468e127 | ||
|
b7ae4a2cfd | ||
|
039205560a | ||
|
801268d5c1 | ||
|
46c536d261 | ||
|
4a8757161e | ||
|
65540c5771 | ||
|
6c1ab24981 | ||
|
61c2ae5549 | ||
|
04711d3b00 | ||
|
cb7c30a4f1 | ||
|
8922c45556 | ||
|
58390c79d0 | ||
|
b7eb1cf936 | ||
|
6e5b9e0ebf | ||
|
c94291558d | ||
|
8d553f7e91 | ||
|
a0be7f0e26 | ||
|
1c3d082b8d | ||
|
2ed211ba15 | ||
|
1161326b54 | ||
|
d473a6d442 | ||
|
8d82033bff | ||
|
9d4cdb7b02 | ||
|
b353e062c7 | ||
|
d8f9b9b61f | ||
|
0b441ade2c | ||
|
6f6fad5a16 | ||
|
465ffa3c9f | ||
|
539c9e0d99 | ||
|
649f962ac6 | ||
|
16bdb3fe51 | ||
|
7c3369e1b9 | ||
|
9eacde212f | ||
|
331647f4ab | ||
|
c2d4822c38 | ||
|
3c30be1320 | ||
|
d8d01bf5aa | ||
|
d42b7228c2 | ||
|
4db057e9c2 | ||
|
ea8e2fc651 | ||
|
10c30ea5b1 | ||
|
84b56d23a4 | ||
|
19d07a4f2e | ||
|
6a5b87dda4 | ||
|
6aac59394e | ||
|
f147163b24 | ||
|
16bf3549c1 | ||
|
b912dafd7a | ||
|
8b3481f511 | ||
|
7019c2685d | ||
|
d18cc38586 | ||
|
cee481f63d | ||
|
e4c8c7188e | ||
|
6c004efd5f | ||
|
1a57780a75 | ||
|
ce25e4aa21 | ||
|
ef4044b62f | ||
|
9ffe5940fe | ||
|
c8d9afce1a | ||
|
285983a555 | ||
|
ab4356aa69 | ||
|
e87d4e9ce3 | ||
|
5fcf047191 | ||
|
c68fb81aa7 | ||
|
e707f78899 | ||
|
41e0ca3f85 | ||
|
c5c10067ed | ||
|
43958614e3 | ||
|
af04906b51 | ||
|
c7e17688b9 | ||
|
ac76840c5d | ||
|
f5885d05ea | ||
|
af949cd967 | ||
|
eee2eb11d8 | ||
|
8d3961edbe | ||
|
4c5328fd1f | ||
|
1472528f6d | ||
|
9416c9aa86 | ||
|
da92c7e215 | ||
|
d27cf375af | ||
|
432a312a35 | ||
|
3a6230af6b | ||
|
ecd267854b | ||
|
ac846667b7 | ||
|
33146b9481 | ||
|
4bace2491d | ||
|
469b3ec525 | ||
|
22017b7ff0 | ||
|
88c11b5946 | ||
|
843252c968 | ||
|
ddea79f0f0 | ||
|
c0e1211abe | ||
|
c8d7f000c9 | ||
|
598f178054 | ||
|
6f8b24f367 | ||
|
5d1b34bdcd | ||
|
8efde799e1 | ||
|
96b61a5f53 | ||
|
a517a8db01 | ||
|
2211504790 | ||
|
fb8662ec19 | ||
|
6f7911264f | ||
|
ae44aff330 | ||
|
b83e8b020a | ||
|
30cd91dc6b | ||
|
09af3ab074 | ||
|
f2fa9c3b31 | ||
|
30a7dfa4f8 | ||
|
62ab477838 | ||
|
1edb7d771f | ||
|
f8a57f7598 | ||
|
85d18fc107 | ||
|
aa00c1d91a | ||
|
a5a88e41af | ||
|
35c928798d | ||
|
83f64a7ff9 | ||
|
60853fa682 | ||
|
b66356be65 | ||
|
efae2dbad6 | ||
|
a7b56a616d | ||
|
bd8b8916a8 | ||
|
57063b6828 | ||
|
69b67a293a | ||
|
d57ddf0be8 | ||
|
43e7e2d663 | ||
|
d355b43dce | ||
|
5d52025266 | ||
|
db470f8529 | ||
|
c8f3d88288 | ||
|
b54cf5bd0a | ||
|
7e4b176323 | ||
|
81bf4f9304 | ||
|
e1967b0700 | ||
|
507091ec8b | ||
|
c7529270ff | ||
|
48ceca4919 | ||
|
0171c71de0 | ||
|
46d0df394f | ||
|
207d3e7b4e | ||
|
426ad81db0 | ||
|
497d2ca306 | ||
|
9d3888a756 | ||
|
c8e090c17f | ||
|
77a74adedd | ||
|
1ccf32e08f | ||
|
b5aced20e1 | ||
|
17af348be8 | ||
|
1afdb05ea9 | ||
|
425b6741c6 | ||
|
d635961120 | ||
|
d5b865da4d | ||
|
89993e4833 | ||
|
6b5da84014 | ||
|
1c3d33e146 | ||
|
71af4b4a85 | ||
|
c49dd50ef3 | ||
|
f66c49bf42 | ||
|
4c9d7dedb3 | ||
|
5336943a8c | ||
|
9dfade5641 | ||
|
a040e521b4 | ||
|
dad4b26c6f | ||
|
0ac364dfae | ||
|
dfd35892f2 | ||
|
79166496f3 | ||
|
c7d12cddec | ||
|
1f09229740 | ||
|
c2d4700571 | ||
|
c06896a352 | ||
|
c119620f7c | ||
|
7f309bb092 | ||
|
e2b67b5700 | ||
|
82a9064d8d | ||
|
a70fab2249 | ||
|
86b45fce6a | ||
|
31a5a4e808 | ||
|
5db86f4c2b | ||
|
20c284c276 | ||
|
befc6cd650 | ||
|
97d95775a5 | ||
|
8f44cd35d8 | ||
|
627a06e30d | ||
|
bfebcfa2c5 | ||
|
56e230863a | ||
|
e5ee47408e | ||
|
f21a707e99 | ||
|
0ef7af76bc | ||
|
18666b3e2d | ||
|
ed87386d7b | ||
|
1ad9b33b08 | ||
|
000b4565c2 | ||
|
eda75fc706 | ||
|
6583add63a | ||
|
441ad841cc | ||
|
6511c5dd7a | ||
|
d5cbb19b39 | ||
|
b0fcc1ad1d | ||
|
417180246c | ||
|
1892562614 | ||
|
22b128dfd2 | ||
|
802fb8b591 | ||
|
c2cf0d9945 | ||
|
3b3ccac212 | ||
|
e61a9077f4 | ||
|
59ce9f9b87 | ||
|
bf54dc082b | ||
|
3ff7bc1f64 | ||
|
7516fe142f | ||
|
b0e4c375a7 | ||
|
d1388d69d0 | ||
|
a3149a41f1 | ||
|
823bd9118e | ||
|
394afc957b | ||
|
63e92d719a | ||
|
9b87131b19 | ||
|
4a15994da0 | ||
|
d0fb537448 | ||
|
59cf1770bc | ||
|
b77f207512 | ||
|
b46a69f5e1 | ||
|
0aaba5ea30 | ||
|
bd6d810d0a | ||
|
e3850fbbbc | ||
|
05d864c913 | ||
|
a3e34f589a | ||
|
a2cf6816ce | ||
|
7b3bc54cc3 | ||
|
cda88e6770 | ||
|
70f1abbc18 | ||
|
bbcafb5d7b | ||
|
d7039ef707 | ||
|
271be92b02 | ||
|
a31baf3c16 | ||
|
e83728897b | ||
|
282a27a07c | ||
|
3fe6dbb65c | ||
|
7547e6a272 | ||
|
1928dafc7e | ||
|
0cbc0f4119 | ||
|
e77b9bf3ee | ||
|
7f7e83a4d9 | ||
|
85fe716d46 | ||
|
85ff3eb8be | ||
|
e55c359cf9 | ||
|
8d7327c188 | ||
|
ca731dca95 | ||
|
d66da21726 | ||
|
1069b05e68 | ||
|
ec0c0d4a28 | ||
|
1739b27231 | ||
|
d9d29af87f | ||
|
7036b704b3 | ||
|
54cda80018 | ||
|
b46e751573 | ||
|
6a2ea94b39 | ||
|
4674b03661 | ||
|
e2f1964389 | ||
|
922de32290 | ||
|
7896bc7831 | ||
|
da07459bd6 | ||
|
3ca205446e | ||
|
eff1931283 | ||
|
3a37a49690 | ||
|
fd8ae54fa7 | ||
|
79fdee3979 | ||
|
a754c0d476 | ||
|
7208169db3 | ||
|
94dac10be7 | ||
|
d5fcbcd89f | ||
|
7b5d43cc00 | ||
|
c5ccedb694 | ||
|
858b29f425 | ||
|
7db76f8809 | ||
|
bcf695913f | ||
|
23cd1d41fb | ||
|
62f5369237 | ||
|
59fc17f4e3 | ||
|
26c1d42fff | ||
|
c1aa755a3c | ||
|
b3d9f2b4a2 | ||
|
29c2fbdbc1 | ||
|
4b9f98f933 | ||
|
e9870b8d25 | ||
|
e0c74fa082 | ||
|
5b93a97281 | ||
|
bdf74c6749 | ||
|
d6f9a8d752 | ||
|
e357d8678c | ||
|
b1b407a0b4 | ||
|
6c3d1649a6 | ||
|
14cf3e138b | ||
|
afbabebfd5 | ||
|
8c0a2741ae | ||
|
1d078e1119 | ||
|
d90baa8601 | ||
|
d5660cd37c | ||
|
63cec45597 | ||
|
f07e24db8f | ||
|
5d5be3e96a | ||
|
6e7649360f | ||
|
1dd38721b3 | ||
|
6a001e4971 | ||
|
96e6a6ac3f | ||
|
2556eb2733 | ||
|
d29ea386d6 | ||
|
a0ee569091 | ||
|
3f4eb9be08 | ||
|
5ea2d1eb67 | ||
|
ffc38a2237 | ||
|
360aff4a57 | ||
|
d26191373a | ||
|
4c06aa98b5 | ||
|
1b267b6599 | ||
|
dd6efb73f7 | ||
|
dfeed1c1a4 | ||
|
0071e3c99c | ||
|
0feec14b15 | ||
|
975f84494c | ||
|
7c86734d2e | ||
|
8665e1de87 | ||
|
c16efc9ab8 | ||
|
324c95d37f | ||
|
69806e0a46 | ||
|
ad15a4b755 | ||
|
002a4b03a4 | ||
|
96476430a3 | ||
|
73db44b00c | ||
|
b32d25942d | ||
|
fce705a92b | ||
|
6164c90f70 | ||
|
e036b899a3 | ||
|
8c7b90ebbf | ||
|
38d9d2ea0e | ||
|
384d30b675 | ||
|
add61868c6 | ||
|
b599f3084f | ||
|
a7493e26e1 | ||
|
ae3a1d7c01 | ||
|
e39e3d5c26 | ||
|
1e7d48846a | ||
|
6001edeecd | ||
|
ce0b7834ff | ||
|
3ac92689f0 | ||
|
1c0836946f | ||
|
bccbe323b7 | ||
|
d73249a793 | ||
|
cd9a03f86c | ||
|
b47c21c683 | ||
|
6de5303e3f | ||
|
2a2fb68b2f | ||
|
844ebb7838 | ||
|
332cc1cd58 | ||
|
e7ce83016e | ||
|
bf6a39eb84 | ||
|
42382e2cde | ||
|
f8e4650791 | ||
|
e444b3c140 | ||
|
d56ac216f4 | ||
|
420a412234 | ||
|
90c643f3ab | ||
|
1d4e380231 | ||
|
6d293ba899 | ||
|
aa086e5407 | ||
|
cce0940e1f | ||
|
daed3e5b6a | ||
|
e2a7f3e2ab | ||
|
5a351b4b00 | ||
|
6f2abbf79c | ||
|
bef1e628ac | ||
|
7340a163a4 | ||
|
a6622b176b | ||
|
771a5e26bb | ||
|
be278f9dba | ||
|
6479e26904 | ||
|
1c7053c9d8 | ||
|
596d0289f8 | ||
|
7df7054bdc | ||
|
5377aac936 | ||
|
ceb6c172ad | ||
|
7f52c1d3a2 | ||
|
af1e16b934 | ||
|
2257181ca8 | ||
|
7e75d48cc4 | ||
|
6330db89a7 | ||
|
f05d6b3711 | ||
|
cce9d3125d | ||
|
e381ce57e2 | ||
|
5dbce6a2bd | ||
|
5b0e88339a | ||
|
db43891f2b | ||
|
f72063e7c2 | ||
|
36a3a78952 | ||
|
2d1597bf10 | ||
|
edfa3e9b14 | ||
|
6fa3565dac | ||
|
7dec8e5caa | ||
|
49abf6007a | ||
|
f0cdf71ccb | ||
|
8655b92e93 | ||
|
e1c6992c55 | ||
|
486b223e01 | ||
|
d53fd29e34 | ||
|
4f89bfac48 | ||
|
5fee96b404 | ||
|
12873f916b | ||
|
efa180392b | ||
|
6d9ed398e3 | ||
|
6d3dbb43a4 | ||
|
811f546ea6 | ||
|
ead8a4e4de | ||
|
05f132c136 | ||
|
5f2c8ac38f | ||
|
14511053aa | ||
|
8353532a09 | ||
|
1c62af0c95 | ||
|
f103ac7640 | ||
|
274e06a48d | ||
|
a39f306184 | ||
|
69d11daef6 | ||
|
057e8b4358 | ||
|
18c0e54e4f | ||
|
85007fa9a7 | ||
|
5c5bf41afe | ||
|
5dba53a223 | ||
|
2bcd9eb9e9 | ||
|
5a54db2f3c | ||
|
b47542b003 | ||
|
14b63ede8c | ||
|
b07c5966a6 | ||
|
c7db72e1da | ||
|
dc5df57c26 | ||
|
a9c97e5253 | ||
|
53e5ef6b4e | ||
|
8800b5c01d | ||
|
280036fad6 | ||
|
a6e1f5ece9 | ||
|
fedd671d68 | ||
|
b7c22659e3 | ||
|
c9c0c01de0 | ||
|
e442b1d2b9 | ||
|
e9f4ff227e | ||
|
668bbe0528 | ||
|
e045a45e48 | ||
|
2c9fc18903 | ||
|
d4eecac108 | ||
|
ef351e0234 | ||
|
05adeed1fa | ||
|
15f1b19136 | ||
|
154fa45422 | ||
|
e35becebf8 | ||
|
bdd36c2d34 | ||
|
0a0156c946 | ||
|
100d9333ca | ||
|
a4cc416511 | ||
|
2ea5793782 | ||
|
0ddf915027 | ||
|
067db686f6 | ||
|
ed2b4b805e | ||
|
8375aa72e2 | ||
|
6334e4bd84 | ||
|
86ce8aac85 | ||
|
de46f86137 | ||
|
5616b08229 | ||
|
8682a57ea3 | ||
|
662a37ab4f | ||
|
42947c9840 | ||
|
3749729d5a | ||
|
fb8b075110 | ||
|
1c5391dda7 | ||
|
f2d10e9465 | ||
|
796d3fb975 | ||
|
5c04bdd52b | ||
|
17143dbc51 | ||
|
1c8bba36db | ||
|
95b329b64d | ||
|
de1d9df787 | ||
|
6450207713 | ||
|
edc4bb4a49 | ||
|
a21ee33180 | ||
|
bcaa31ae33 | ||
|
0cc1726781 | ||
|
aad78840a0 | ||
|
e3ab665e90 | ||
|
1a91792e7c | ||
|
670c37b428 | ||
|
040dacd5cd | ||
|
59541de437 | ||
|
fc8551bcba | ||
|
c2c97c36bc | ||
|
211fdde742 | ||
|
366cbb3e6f | ||
|
a318624fad | ||
|
3cf5981146 | ||
|
4cc065e66d | ||
|
ba731ed145 | ||
|
b77460ec34 | ||
|
88bee6c68e | ||
|
1f84d6344b | ||
|
699fbd64ab | ||
|
b42bf39fb7 | ||
|
5368d51d63 | ||
|
c5db012c9a | ||
|
b70d986bfa | ||
|
973628fc1b | ||
|
91fea7c956 | ||
|
d378d789cf | ||
|
9007d6621a | ||
|
774ec49396 | ||
|
bba55faae8 | ||
|
8f2b0772f9 | ||
|
1a409dc7ae | ||
|
404ea0270e | ||
|
ef939dee74 | ||
|
f1576eabb1 | ||
|
49c4345c9a | ||
|
f94182f77d | ||
|
222a77dfe7 | ||
|
24ceee134e | ||
|
04c8a73889 | ||
|
9a75501152 | ||
|
f6fbbc17a4 | ||
|
15dc3868c3 | ||
|
2525d7aff8 | ||
|
a5d2137ed9 | ||
|
a8e51e686e | ||
|
a2429ef64d | ||
|
1b88678cf3 | ||
|
0e96852159 | ||
|
19a61d838f | ||
|
4eec302e86 | ||
|
f3885aa589 | ||
|
b493c81ce8 | ||
|
9ef62194c3 | ||
|
91ee4aa542 | ||
|
e3caff833c | ||
|
b2995e4ec4 | ||
|
ccd3aeebbc | ||
|
7a033a1d55 | ||
|
1652d8bf4b | ||
|
c85f275bdb | ||
|
a923f4e7c0 | ||
|
82af8e455e | ||
|
1baee488ab | ||
|
7433b70d95 | ||
|
de6c71a426 | ||
|
16a34548ea | ||
|
b2f3ab77cd | ||
|
b2f6ed7dee | ||
|
09e34d29cd | ||
|
667a6981ea | ||
|
cf1d9f5612 | ||
|
55b03a41b2 | ||
|
81b4ffa6b4 | ||
|
8c1821228d | ||
|
9c5c1a09a1 | ||
|
09fa99fdc6 | ||
|
8331939aed | ||
|
02213d6e07 | ||
|
387df0ee1f | ||
|
b59035df06 | ||
|
5517e62c86 | ||
|
5dca5225dc | ||
|
c005c90746 | ||
|
8bdd0bb82f | ||
|
a790935d02 | ||
|
1fcbbd3b9d | ||
|
b9077d3ea2 | ||
|
1d7d84540f | ||
|
6f471d1c5e | ||
|
ff95292435 | ||
|
e8a8a7b8cc | ||
|
b0ad8ec023 | ||
|
ab2bfd7f8c | ||
|
29f1c40580 | ||
|
2585e72a30 | ||
|
837fca1368 | ||
|
0c995c1ea7 | ||
|
ad244ab744 | ||
|
308ceee46c | ||
|
e0195da80d | ||
|
b02f40b392 | ||
|
c0fe32c4ec | ||
|
e9f93a1de9 | ||
|
c14388629a | ||
|
3c1f84a9e9 | ||
|
398a995798 | ||
|
dc86b2063a | ||
|
bbab1013c5 | ||
|
1945499e2f | ||
|
c971debd15 | ||
|
161c7e9fce | ||
|
fd3ebc13f7 | ||
|
9db4b949f2 | ||
|
5b5726bdd4 | ||
|
1347bb2e4b | ||
|
286191ecb7 | ||
|
096bcdd078 | ||
|
7d7739e031 | ||
|
3470810709 | ||
|
98b43bb24f | ||
|
275c54e810 | ||
|
9a05037352 | ||
|
143f9c78be | ||
|
75f0aaf4a1 | ||
|
c36df6a78b | ||
|
10a6bd67de | ||
|
db17ba54b4 | ||
|
c2f64a52da | ||
|
0b81c6a6c4 | ||
|
36bd4cdc43 | ||
|
87eea16d7b | ||
|
0aa6d3d4bc | ||
|
43dbff938e | ||
|
54aebb92fd | ||
|
f0c7649158 | ||
|
93445b4dbc | ||
|
aeaa876d57 | ||
|
9c1e08249d | ||
|
33a60fe919 | ||
|
85982dc8e9 | ||
|
dbe02d398a | ||
|
e022e2e13c | ||
|
7084d38767 | ||
|
00e0f3bd2b | ||
|
cd7212453e | ||
|
a69f2b09da | ||
|
878fe80ca3 | ||
|
8331c1f858 | ||
|
f4a69d2827 | ||
|
ed6cef85d8 | ||
|
d315f73080 | ||
|
06ec5393d7 | ||
|
1a491fc10c | ||
|
488db81e36 | ||
|
f377d9f057 | ||
|
db4e942b0d | ||
|
68b96bdf1a | ||
|
4f7a760a94 | ||
|
da5077fa5f | ||
|
f1231bb97d | ||
|
80eb1ad936 | ||
|
cc5303e1c8 | ||
|
f6a5948f58 | ||
|
f6eed8091e | ||
|
4a8a52bad9 | ||
|
c09aabab0c | ||
|
d47ba2b2ef | ||
|
17fb1ceed8 | ||
|
97ff67e54a | ||
|
d4204a42fd | ||
|
c6f6940459 | ||
|
d739a6bb2f | ||
|
0982c66051 | ||
|
d40701463f | ||
|
405692d793 | ||
|
7938748d77 | ||
|
e909f84966 | ||
|
8a153ed38e | ||
|
eb16986f32 | ||
|
bd801de236 | ||
|
9c3bcd48ee | ||
|
ee23b947aa | ||
|
0f7341bdde | ||
|
602b5aaf01 | ||
|
70bbb3e280 | ||
|
a27eebb225 | ||
|
1b0326f773 | ||
|
93a1693040 | ||
|
df7ed24389 | ||
|
544aa00c17 | ||
|
fc22453618 | ||
|
fefcb8c9f8 | ||
|
9cf5dd0291 | ||
|
7a1f033c1d | ||
|
4a5acad414 | ||
|
227e96469c | ||
|
c93fa6effe | ||
|
102fb94524 | ||
|
c25d624524 | ||
|
12ab8b7af3 | ||
|
097bec473c | ||
|
d36b5d7d55 | ||
|
4b858b6466 | ||
|
e03e3c4582 | ||
|
91f1edbdd4 | ||
|
c6e2a4ebd8 | ||
|
3eefb5f2ad | ||
|
04b19359cb | ||
|
f2ef781efd | ||
|
60b0fb3e88 | ||
|
f323d70c0f | ||
|
03f316e7a2 | ||
|
79b7f0d592 | ||
|
d25aebdaf5 | ||
|
1454ba4a9e | ||
|
4781df587c | ||
|
e49330d6ee | ||
|
dbe6eb20c8 | ||
|
8bec5beb4b | ||
|
e6effb8245 | ||
|
5e32655830 | ||
|
270f91e577 | ||
|
07858e8f71 | ||
|
4cb5a4f609 | ||
|
cb57c3c916 | ||
|
92b1166dd0 | ||
|
e6c28982dd | ||
|
64f69718fb | ||
|
1301e69c7d | ||
|
99b8f0902e | ||
|
6a4d322a7c | ||
|
9d7f358d4b | ||
|
b1bb5a4796 | ||
|
f8ae086334 | ||
|
c49bda7319 | ||
|
aa9022d638 | ||
|
2994ba33ac | ||
|
87c0f135dc | ||
|
a687013fbe | ||
|
b0097fd0c1 | ||
|
9729b6b75a | ||
|
58959ae82f | ||
|
4ffc106c58 | ||
|
a374301570 | ||
|
bc8e16fc69 | ||
|
947162452d | ||
|
7a730d42dd | ||
|
109391031b | ||
|
aba63f0f9a | ||
|
e67886bf9d | ||
|
c2ac3b51c1 | ||
|
081a9e7bd8 | ||
|
55d8ed093a | ||
|
77149e5d89 | ||
|
28839f6b71 | ||
|
49bcf91aaf | ||
|
28073c76ac | ||
|
50e8a52c74 | ||
|
5c448b6896 | ||
|
c0fd5b2e84 | ||
|
6141b98bf8 | ||
|
2eae207435 | ||
|
9a8e4381be | ||
|
5f034330c5 | ||
|
edea63511d | ||
|
80df4f8b01 | ||
|
68118c2653 | ||
|
1e79dcfcaa | ||
|
1805e95b69 | ||
|
0d0cc8cf9c | ||
|
5bd937ece0 | ||
|
8908a70c19 | ||
|
5ec2467268 | ||
|
e489e70031 | ||
|
05c9169c70 | ||
|
bd49c993de | ||
|
5989680967 | ||
|
e1265b2e7b | ||
|
1721460dcd | ||
|
861bf967a7 | ||
|
09b8314057 | ||
|
151b142d30 | ||
|
b7c4136702 | ||
|
e666fe5a8d | ||
|
9ce34be217 | ||
|
79226d0870 | ||
|
686316b390 | ||
|
6da385de9d | ||
|
0cc5e3ef03 | ||
|
47194c1fe4 | ||
|
3bf40d5db9 | ||
|
a9e11623cd | ||
|
a870dd368e | ||
|
b6b26c710f | ||
|
705ad84ce7 | ||
|
04932f496f | ||
|
dffbd58671 | ||
|
152e0162a9 | ||
|
2fa7faa75a | ||
|
12f514f752 | ||
|
e2886f37a2 | ||
|
03dff09b8a | ||
|
a556f8f2bf | ||
|
1765c9125a | ||
|
ab28192d50 | ||
|
ad15721677 | ||
|
a2d4dbeee4 | ||
|
1712ba1198 | ||
|
040dda37ed | ||
|
a99ba3bb16 | ||
|
05ff4a527d | ||
|
ae5328c500 | ||
|
34ff39e654 | ||
|
8e3915f5bf | ||
|
6019a1006c | ||
|
a1f04e9869 | ||
|
961149b865 | ||
|
597c810ef0 | ||
|
2de6a5676d | ||
|
050578da94 | ||
|
5a437add01 | ||
|
6fc73e3038 | ||
|
d97e9b9e50 | ||
|
fa0eb11bf4 | ||
|
f660c29348 | ||
|
6613895de0 | ||
|
803d52ffce | ||
|
fc61f8d52e | ||
|
0553814b4f | ||
|
f1566cb8c2 | ||
|
c1ba8e1b3a | ||
|
2ff7ab8d40 | ||
|
93698a8f73 | ||
|
6245587dc8 | ||
|
2faf53b039 | ||
|
e0b1787740 | ||
|
9849dba5d3 | ||
|
03c9c091f2 | ||
|
5a8b68a429 | ||
|
34d88ea6d9 | ||
|
0665b45e61 | ||
|
648fcf3a2e | ||
|
058438a25d | ||
|
6e938a3106 | ||
|
2f93d62aa5 | ||
|
8ba3d7ec75 | ||
|
9e2d282709 | ||
|
706c7cb4f1 | ||
|
5884eeb606 | ||
|
e7ee19bd66 | ||
|
2f8fc92182 | ||
|
f59d3fc4a3 | ||
|
8e2bae0f2a | ||
|
e6dae03a0d | ||
|
2f2ed116f7 | ||
|
e91c6a7bd1 | ||
|
1ff95e85f4 | ||
|
36924b63dc | ||
|
0c80d3d9fa | ||
|
411510cbe6 | ||
|
6e2b8a5750 | ||
|
ca66a96d0a | ||
|
0c09ec5d13 | ||
|
a8e2110b2d | ||
|
250541d29d | ||
|
142b9e1eff | ||
|
f204212963 | ||
|
91ae87fa60 | ||
|
85646c96ad | ||
|
d6456d13c2 | ||
|
98f7485303 | ||
|
a42d811420 | ||
|
bf6fdce339 | ||
|
fa378f09c3 | ||
|
d9d11e2291 | ||
|
73b2683697 | ||
|
d8a749fd27 | ||
|
f2d2d080f6 | ||
|
78ceef6b15 | ||
|
ca8e59fa85 | ||
|
b0210567aa | ||
|
33ec13293b | ||
|
bedb411d06 | ||
|
ef3e98807e | ||
|
49158dbe40 | ||
|
35682b5228 | ||
|
9cc70e9e70 | ||
|
50598d9d47 | ||
|
fc23f37af7 | ||
|
bfe143808f | ||
|
91742055e0 | ||
|
6c41f64a98 | ||
|
e72dbf3dfc | ||
|
c3b78c3255 | ||
|
fb666c44b3 | ||
|
58b5bf7886 | ||
|
cc70200a07 | ||
|
ffbd98fec6 | ||
|
f3c17361da | ||
|
bdf0238328 | ||
|
39b907cdfb | ||
|
24a7878e7c | ||
|
2364a84579 | ||
|
c6e5be91e9 | ||
|
ce22c0e6a4 | ||
|
bd60df97aa | ||
|
94df580674 | ||
|
90e5f8ffe1 | ||
|
bf6168fca8 | ||
|
a78e861a89 | ||
|
3550e3c145 | ||
|
8425c2363b | ||
|
15ec44901d | ||
|
924cc11af6 | ||
|
0fa5a252b9 | ||
|
fe46349786 | ||
|
96a2b386f2 | ||
|
214e08f8c9 | ||
|
8bd3b50e31 | ||
|
b8c4bd200e | ||
|
e70f27dd79 | ||
|
b680cdd0e4 | ||
|
c9f63e5016 | ||
|
d8a197ca51 | ||
|
1f9841f609 | ||
|
aa21edeb53 | ||
|
eb69f126de | ||
|
70edccf7e0 | ||
|
4b80a7f6fe | ||
|
e06e6895da | ||
|
50fc82acdc | ||
|
ea67bb6e41 | ||
|
b19f2e2d3d | ||
|
9c48f666ec | ||
|
4990eec4a2 | ||
|
bf8c8976dd | ||
|
a7ec0ed587 | ||
|
1a1fe99669 | ||
|
8818073ff3 | ||
|
b35e6558bc | ||
|
5e22574402 | ||
|
e1873ab872 | ||
|
29312a3ec0 | ||
|
feeb701c13 | ||
|
b347aefd61 | ||
|
abfa1636e4 | ||
|
deca5ec903 | ||
|
05b9f14b76 | ||
|
4cb576da19 | ||
|
8cb644fbec | ||
|
22996babcf | ||
|
75ad868cbd | ||
|
9433fe46c8 | ||
|
935c5093e2 | ||
|
6bb47d8adb | ||
|
57eefdd458 | ||
|
060d25fc79 | ||
|
4ce970c0b2 | ||
|
017df7113d | ||
|
00fe3d5094 | ||
|
bcac3c62a2 | ||
|
2a82dff3ae | ||
|
16ec5939c2 | ||
|
b064274e27 | ||
|
ae003af262 | ||
|
f515898cb5 | ||
|
25bab0e976 | ||
|
8213b1802b | ||
|
4c1e0b188d | ||
|
09b23f96d7 | ||
|
56f389a9f3 | ||
|
45e12df8a3 | ||
|
1892cd65f6 | ||
|
d3ca9d1db9 | ||
|
16ad344c41 | ||
|
8ca2a9a7d5 | ||
|
93cbcb61b8 | ||
|
276c450759 | ||
|
a6a6e843af | ||
|
f54f63ec3f | ||
|
93951f2ed5 | ||
|
c29b21717d | ||
|
80d16e6c91 | ||
|
68cfb9a053 | ||
|
d50fe9550c | ||
|
8f5c4dcd2e | ||
|
1a802726d2 | ||
|
90c867b424 | ||
|
eeb77369cb | ||
|
69a48cbdd7 | ||
|
33b8ad0d89 | ||
|
605cfeb3e4 | ||
|
c6588856c7 | ||
|
dba645421f | ||
|
f437ac0b27 | ||
|
8ec6729cae | ||
|
19d4b5dd04 | ||
|
78251b0304 | ||
|
10e54eca26 | ||
|
a8740c6e13 | ||
|
06391b6dd9 | ||
|
8dc01df60b | ||
|
a9de6dde33 | ||
|
75571ed303 | ||
|
1912df7e3e | ||
|
bacbb2a0ca | ||
|
e1ba25a4fb | ||
|
10a17cfe54 | ||
|
5a311236c4 | ||
|
a7b8708dfc | ||
|
8964dc53df | ||
|
ecc3a0aec5 | ||
|
144743e818 | ||
|
7712bd0c76 | ||
|
101686c665 | ||
|
f2ca929a4a | ||
|
13f2b3d134 | ||
|
50204d9551 | ||
|
6852f821a5 | ||
|
953bc8dee2 | ||
|
9afd3f0c32 | ||
|
3f443f3878 | ||
|
5dd85197af | ||
|
764a851189 | ||
|
b98cb74f5e | ||
|
750db9139a | ||
|
f2c8b393e1 | ||
|
fd59556222 | ||
|
0b54e8e04c | ||
|
85b3526617 | ||
|
7ff8fc259b | ||
|
cc507d7ace | ||
|
7c0fbe2959 | ||
|
6bc60e021e | ||
|
54816f1217 | ||
|
be3283c9ba | ||
|
249b0a2a80 | ||
|
71d476b121 | ||
|
45d8797dce | ||
|
b6e21a18cc | ||
|
f959cc296f | ||
|
ab44beba17 | ||
|
b2a0b649fd | ||
|
6179405e84 | ||
|
83d945127f | ||
|
1be15a0864 | ||
|
41b44739b1 | ||
|
38ca58ae8d | ||
|
fd7829d468 | ||
|
d62836f2ab | ||
|
4fd03b93f7 | ||
|
1617a6ea8e | ||
|
e9ce7243b8 | ||
|
d036a04d4d | ||
|
35ad57674e | ||
|
437189c213 | ||
|
0f5fd1edc0 | ||
|
b5aaaf864d | ||
|
d948839320 | ||
|
a5af58c05a | ||
|
d8a61b94a9 | ||
|
fda05df5f1 | ||
|
3997aa9a0f | ||
|
81292f9cf3 | ||
|
167e293594 | ||
|
1f9ccfe54d | ||
|
d3d0360526 | ||
|
826b0f384d | ||
|
a3131e271a | ||
|
ed12936be2 | ||
|
7c00ce5f30 | ||
|
c87bd53352 | ||
|
af1c93cdfc | ||
|
9ce7fc9b2c | ||
|
b6243bfc1c | ||
|
21ea079896 | ||
|
93579773d6 | ||
|
0bd23f720d | ||
|
dca3bf0e80 | ||
|
c605a05c6b | ||
|
c44f13114f | ||
|
ef7076e36f | ||
|
324106e91e | ||
|
218b2a5992 | ||
|
61e7afa9f0 | ||
|
367566adaa | ||
|
c06f482901 | ||
|
965fe1db94 | ||
|
f6be326feb | ||
|
c58e5e80ce | ||
|
641a2a8bb4 | ||
|
7d497e46c5 | ||
|
d414588a47 | ||
|
79de8ff169 | ||
|
38daee41d5 | ||
|
f8f55bc413 | ||
|
7457ce7f2d | ||
|
01dbc909be | ||
|
0512c22607 | ||
|
f0d5a96464 | ||
|
361645e8b6 | ||
|
353d44a4a6 | ||
|
680aa60429 | ||
|
6b3cf8c4b8 | ||
|
e41766fd58 | ||
|
e4c820c35e | ||
|
db5f83f8c9 | ||
|
412d560bcf | ||
|
a468954519 | ||
|
a3d3f27aaa | ||
|
72b68c7f82 | ||
|
28333d4513 | ||
|
ed8c0ee95a | ||
|
724a316204 | ||
|
d70cafc1e4 | ||
|
18c8e0a14a | ||
|
3ff6a2e7ff | ||
|
1ee3ff738e | ||
|
52edd4c9bc | ||
|
d8345c5eae | ||
|
98e7a07fba | ||
|
3d5988577a | ||
|
69603aed34 | ||
|
299e35ebe4 | ||
|
6674be2572 | ||
|
cf1566e8ed | ||
|
c6d91b89d7 | ||
|
b44f7957d5 | ||
|
aead0e3a69 | ||
|
b0484fe3e5 | ||
|
b8cd9403df | ||
|
d7df577898 | ||
|
09bccc97ba | ||
|
1c187e9729 | ||
|
8939196f0d | ||
|
15be42abfd | ||
|
ca45d5ffbe | ||
|
2bec26dba5 | ||
|
03c8d0113c | ||
|
536606c2ed | ||
|
6e29a47784 | ||
|
826a440fa6 | ||
|
baff4e61cf | ||
|
4d7eca7d2e | ||
|
32fec3bb74 | ||
|
3134dd4c0d | ||
|
56a9c7a802 | ||
|
bfa468c771 | ||
|
6318bb9f96 | ||
|
8618a3119b | ||
|
27a268df33 | ||
|
7930f6fa0a | ||
|
49bd208026 | ||
|
83fe607f62 | ||
|
ea8b799ff0 | ||
|
e2d6f8d897 | ||
|
0924c2510c | ||
|
065292f8a4 | ||
|
35f248dff0 | ||
|
b09fe64ff1 | ||
|
54debdbda2 | ||
|
b6341287bb | ||
|
6a92e34994 | ||
|
00efc63f74 | ||
|
b061cce913 | ||
|
c929b5e82e | ||
|
58f48500b1 | ||
|
b5125e59ab | ||
|
d316b02d28 | ||
|
7910198b93 | ||
|
7b2f35c7d4 | ||
|
45874a23bb | ||
|
9c3b573f8e | ||
|
7d6ef61491 | ||
|
6a7c3c6e3f | ||
|
883194afec | ||
|
3a63aa6b1e | ||
|
337499d772 | ||
|
82123f3c4e | ||
|
8f3d820664 | ||
|
7d812f8112 | ||
|
473a8beff0 | ||
|
0d675cdd1a | ||
|
9cce46ea8c | ||
|
2e67289473 | ||
|
980aeafebe | ||
|
7d1ab3374e | ||
|
01b9b263ed | ||
|
c33a049292 | ||
|
7eaa7c957a | ||
|
f055ba7965 | ||
|
157c247563 | ||
|
a35b6dc1af | ||
|
910a821d0b | ||
|
2c21e7bd3a | ||
|
45a177e2a0 | ||
|
0c51352a74 | ||
|
9b1980cfff | ||
|
ae29296e20 | ||
|
75e743bfae | ||
|
2f19d964f6 | ||
|
0d2990510e | ||
|
e732df56a1 | ||
|
2f92d6bca3 | ||
|
c72903e8d6 | ||
|
ded58d3b66 | ||
|
be9414fabe | ||
|
033afe1574 | ||
|
c35461a005 | ||
|
a93421019b | ||
|
4fd3e2ece7 | ||
|
937adec515 | ||
|
bce3f282f1 | ||
|
f8ad44a99f | ||
|
7ee2f0d918 | ||
|
9cbb373ae2 | ||
|
484df62c5a | ||
|
79a6b72a13 | ||
|
d439564a7e | ||
|
b0a5f265e3 | ||
|
8800eb3492 | ||
|
09308d6125 | ||
|
a8822e24b0 | ||
|
a60e4c0a3f | ||
|
b2d740dd1f | ||
|
3237b2702f | ||
|
e8c49b0090 | ||
|
3dd51cd648 | ||
|
e03aa795fa | ||
|
a8a05a21a4 | ||
|
63fa406c3c | ||
|
6ad6609872 | ||
|
474fbf09c4 | ||
|
47849b8ff7 | ||
|
0379a52f03 | ||
|
bc2eeb0560 | ||
|
81f07c3783 | ||
|
f90926389a | ||
|
dcb97e775e | ||
|
096de82fd9 | ||
|
db693d46df | ||
|
b8d628c5f3 | ||
|
0aa22998e2 | ||
|
afe047a77f | ||
|
1ae794e5e4 | ||
|
a7a204ebca | ||
|
8774d7e4d5 | ||
|
34e51ac1cb | ||
|
d152dc2e6a | ||
|
8ce5a9dd19 | ||
|
820d8e6ce6 | ||
|
3cefd60c37 | ||
|
876d4de6be | ||
|
974902af31 | ||
|
45626a05dc | ||
|
4b5299bb7a | ||
|
ceab27c97a | ||
|
03d1b56a8f | ||
|
64190dfc73 | ||
|
29128eb316 | ||
|
ea9f8b4258 | ||
|
1cb03a184b | ||
|
158d998ec4 | ||
|
168241df4f | ||
|
f5417032bf | ||
|
d69db3469e | ||
|
980a4fa401 | ||
|
027e2e8a11 | ||
|
dcfda9d9d2 | ||
|
ca73e29ec5 | ||
|
0330442c63 | ||
|
221c6a8eef | ||
|
25a1e5f952 | ||
|
38df80046e | ||
|
57bb7aa5f6 | ||
|
86996704ce | ||
|
f53ac2a5a0 | ||
|
d0af5979c8 | ||
|
43020bd064 | ||
|
dc00b96f47 | ||
|
71c856878c | ||
|
19865e81db | ||
|
a4258b1244 | ||
|
e0b76b185a | ||
|
c47f441b13 | ||
|
7c854a18bb | ||
|
8df2c0a7c6 | ||
|
e60b9f796e | ||
|
2c8bcc6722 | ||
|
e257d92f41 | ||
|
f697338eec | ||
|
e2ec7c76a4 | ||
|
058d101bf9 | ||
|
833794feef | ||
|
a3dedb68d1 | ||
|
4a463567ac | ||
|
9f3ed7d855 | ||
|
221b429c24 | ||
|
b937d1cd9a | ||
|
986c46c2b6 | ||
|
e029216566 | ||
|
2d4595887d | ||
|
2beffe688a | ||
|
66408a87ee | ||
|
62b418cd16 | ||
|
5361cc075d | ||
|
be12164290 | ||
|
588896712e | ||
|
6221b94fdf | ||
|
efef80f67b | ||
|
0c1a0ab966 | ||
|
678ed5ced5 | ||
|
7f87ce0362 | ||
|
d1acf7f192 | ||
|
171d2ce59c | ||
|
c6170eb79d | ||
|
d2c44dd4df | ||
|
9b7090ca1d | ||
|
ee8e88b111 | ||
|
a901b1f0d7 | ||
|
82efd95901 | ||
|
4c803d579b | ||
|
b34ec6c46b | ||
|
6368c626c5 | ||
|
a5445d9c5c | ||
|
da86457cda | ||
|
eb00693325 | ||
|
a15a0b5eb9 | ||
|
646fd5f47b | ||
|
277b347604 | ||
|
12bc634ec3 | ||
|
769e54d8f5 | ||
|
ad50bc4ccb | ||
|
0ca7aa126b | ||
|
d0d9967457 | ||
|
b51b52ac0e | ||
|
36c1f32ef9 | ||
|
fa245ffdd5 | ||
|
f7c5f45833 | ||
|
579976260f | ||
|
d56e9f6b80 | ||
|
57b0b6a9b1 | ||
|
640190217d | ||
|
a08f485d76 | ||
|
f6b66839bd | ||
|
26700e7882 | ||
|
d86229dc2b | ||
|
f56171b513 | ||
|
516e9a4de6 | ||
|
765d907ea1 | ||
|
287421e21e | ||
|
2761fda2c9 | ||
|
339e36fbe6 | ||
|
5e648b96e8 | ||
|
ac2135e450 | ||
|
68c8c05775 | ||
|
14b1cab5d2 | ||
|
e570e2e736 | ||
|
16fd2e5d68 | ||
|
422b25ab1f | ||
|
b7527399b5 | ||
|
89bad11ad8 | ||
|
9d32e2c3b0 | ||
|
099341582a | ||
|
942c98003f | ||
|
cad3bf3e8c | ||
|
2ab5cc73cd | ||
|
9f2dd09628 | ||
|
2798adc837 | ||
|
54d9404c0e | ||
|
f1025dce4e | ||
|
538f4dad9d | ||
|
5323e232b2 | ||
|
5d9986ab5f | ||
|
38688a4486 | ||
|
d640a57f9b | ||
|
5e9479cded | ||
|
06ffe44f1f | ||
|
b35b816287 | ||
|
bf15d06568 | ||
|
2c2ffa846c | ||
|
48c41bcbe7 | ||
|
beb47e1c63 | ||
|
303c3654a1 | ||
|
5fab610fab | ||
|
3c3ebc05cc | ||
|
94956ebde9 | ||
|
e716bed11b | ||
|
ccbcad9741 | ||
|
15a8c34717 | ||
|
b815f48803 | ||
|
95c97332bf | ||
|
9bdf6b00cc | ||
|
91b23caa19 | ||
|
5df48ef8fd | ||
|
109078c5e0 | ||
|
c0b262a22a | ||
|
8bb1af9926 | ||
|
538f1f1a68 | ||
|
b60ab3ae44 | ||
|
370a0635fa | ||
|
db2ca014cb | ||
|
f0f8379e1b | ||
|
815eebf1d7 | ||
|
95cf18ff00 | ||
|
696fcaf391 | ||
|
6ff5ccc938 | ||
|
f8a18fcaca | ||
|
961c1be53e | ||
|
eda1dcb7f6 | ||
|
5e0140d62c | ||
|
717fe3cf3a | ||
|
32d80ca438 | ||
|
2a9aead50e | ||
|
9fda84b1c9 | ||
|
42702dc1a3 | ||
|
40e35b3fa6 | ||
|
b15d41a96a | ||
|
7da2083986 | ||
|
37df9a10ff | ||
|
0f845fb350 | ||
|
23b8998701 | ||
|
401d441c10 | ||
|
f7aea8ed89 | ||
|
a9b67d586b | ||
|
b1fbead531 | ||
|
b06826e88a | ||
|
57fef8f75e | ||
|
f599a4a859 | ||
|
e44b0727d5 | ||
|
18cee65c4b | ||
|
f779cb93d6 | ||
|
aec5080a47 | ||
|
80418a44d5 | ||
|
257c20f39e | ||
|
050de3ab7b | ||
|
f1498d4b53 | ||
|
18d19d9ed4 | ||
|
61d7d1459a | ||
|
6924c6e5a3 | ||
|
85c851f519 | ||
|
5cd7d1a3c9 | ||
|
8b67159239 | ||
|
4f70da2731 | ||
|
db5040e6ea | ||
|
97764921ed | ||
|
a6853cb79d | ||
|
8c15db53b2 | ||
|
0200138a5d | ||
|
14af98ebdc | ||
|
8a5434419b | ||
|
8a406be48a | ||
|
feac802456 | ||
|
076f254a67 | ||
|
bc3a8a0039 | ||
|
45d151a69d | ||
|
bd014c409b | ||
|
08421aad3d | ||
|
1c25ed669c | ||
|
a005d19f6f | ||
|
471589f1f4 | ||
|
b0ee1f6cc6 | ||
|
79128dcd6b | ||
|
dd7e1469e9 | ||
|
186ec13579 | ||
|
2c4e6b65d7 | ||
|
108a6297e9 | ||
|
94d4ce5a6f | ||
|
81da231b1e | ||
|
1a87dcd9b9 | ||
|
a1fff30bd9 | ||
|
81d57fe658 | ||
|
3118437e10 | ||
|
65e461a7c0 | ||
|
c672681ce5 | ||
|
d332a254ee | ||
|
f3c072f6b6 | ||
|
3debb8aab5 | ||
|
aada6e7e40 | ||
|
ac60786c6f | ||
|
db33dc6938 | ||
|
9dfb25cafd | ||
|
df8d2285b6 | ||
|
af6456d1ea | ||
|
6f57f7dd2f | ||
|
fd2ff675c3 | ||
|
bec23c8a41 | ||
|
faaff8bd72 | ||
|
8031c6c1e7 | ||
|
9d8fc8caad | ||
|
d1b1add176 | ||
|
a51b729817 | ||
|
19bc79b1a6 | ||
|
d2fa3c7796 | ||
|
03cac2109c | ||
|
932935ecc7 | ||
|
e01118d36d | ||
|
dea9304968 | ||
|
2864e13ff9 | ||
|
a8c5a0afdc | ||
|
0ba336b04e | ||
|
89f1223f64 | ||
|
8bc0710073 | ||
|
fb591bf232 | ||
|
a43e0d3f95 | ||
|
f16cc1f08d | ||
|
8712bddcbe | ||
|
99dbc6d780 | ||
|
75e4cc2fd9 | ||
|
81cb302399 | ||
|
3bcdf46937 | ||
|
1cf6a99df4 | ||
|
a5d165dc85 | ||
|
f18e77f1db | ||
|
2fc02ed456 | ||
|
9db61c45ed | ||
|
8cb54cd74d | ||
|
a3f1ce25f8 | ||
|
3c7f682e90 | ||
|
8984096f35 | ||
|
1ce7831f6d | ||
|
46f6c09d21 | ||
|
6fe2248314 | ||
|
cb4f797d32 | ||
|
eb40ac163f | ||
|
27ec548b88 | ||
|
637f09f140 | ||
|
9b0f57a0a6 | ||
|
5f02068f90 | ||
|
7f74906d33 | ||
|
56523812d3 | ||
|
602b2d198a | ||
|
4d95bb1421 | ||
|
184ac6a4e6 | ||
|
10e0fe86fb | ||
|
7e1645845f | ||
|
f255ce3f02 | ||
|
07ecef86e3 | ||
|
3bc4b4c174 | ||
|
da089b5fca | ||
|
d4f094cc11 | ||
|
494a6512b8 | ||
|
3732c3a9b1 | ||
|
f6a63d88a7 | ||
|
86cc703c75 | ||
|
4dba34bd02 | ||
|
b0437516c1 | ||
|
da015e0249 | ||
|
554857da97 | ||
|
9bf23fa43b | ||
|
42287066d3 | ||
|
a1ff1de975 | ||
|
1bfbc5bbc4 | ||
|
c5b4d3ceaa | ||
|
8fc9c5d025 | ||
|
42bba66c02 | ||
|
53bc80bb59 | ||
|
771ce96e6d | ||
|
fc456ff0cd | ||
|
b4f70db878 | ||
|
5707f79b33 | ||
|
0a2f4edfc6 | ||
|
56fa46716e | ||
|
b74abe56fd | ||
|
62aecd1e4a | ||
|
973afef96e | ||
|
a235605d2c | ||
|
023108a733 | ||
|
75d1be8272 | ||
|
a44235d11b | ||
|
7abf6a6958 | ||
|
0d0b1fdf82 | ||
|
b710c72f04 | ||
|
678c316d01 | ||
|
bc6de32faf | ||
|
7cf8ad4dc7 | ||
|
02ec72fa40 | ||
|
d22634a597 | ||
|
4132cee687 | ||
|
f3df0d5f4a | ||
|
1d285e654d | ||
|
dc6ad64ec7 | ||
|
92bfcf0467 | ||
|
54b1fe83f3 | ||
|
5337cff179 | ||
|
1be788f785 | ||
|
8afbf339f7 | ||
|
8c935dfb50 | ||
|
66c5ed8406 | ||
|
4087e97505 | ||
|
da50ed0936 | ||
|
fbbfff3795 | ||
|
fb9103acd3 | ||
|
49d921cf91 | ||
|
fe29c97ae8 | ||
|
2abb6c8689 | ||
|
a3ca441998 | ||
|
9cf503acb1 | ||
|
1cbdd7ed5c | ||
|
428e52e0d1 | ||
|
70dc222719 | ||
|
69f796f0c7 | ||
|
5826f0810c | ||
|
de9443a694 | ||
|
99c5f7e013 | ||
|
d9dedc2cd5 | ||
|
23ae6027ab | ||
|
781b5691c9 | ||
|
fd9bbcb157 | ||
|
e0410661fa | ||
|
8ef754678a | ||
|
161a8f55fa | ||
|
7481cc31e1 | ||
|
b15b6e834f | ||
|
76640cf1a1 | ||
|
374ea7b81d | ||
|
46bef931e9 | ||
|
a36e9ae690 | ||
|
728155a2a1 | ||
|
cdf9a9f4fc | ||
|
29307740dd | ||
|
a038d62644 | ||
|
20c7e31ea3 | ||
|
65065e7fdf | ||
|
352297cf8d | ||
|
a67a50f9c0 | ||
|
324bc41097 | ||
|
c81b443d93 | ||
|
dc16ab92f4 | ||
|
53032a6695 | ||
|
d90a5f291b | ||
|
3b7791501e | ||
|
f2b8a3614d | ||
|
e89b47c7ee | ||
|
2aa66eb12d | ||
|
4c8b93e5b9 | ||
|
216631bf02 | ||
|
c7f3123e28 | ||
|
f599c2a691 | ||
|
bc7d1f36ea | ||
|
80fa294a31 | ||
|
465dfd68bc | ||
|
73f45fbe94 | ||
|
d270678bda | ||
|
de028814e5 | ||
|
b5406b752d | ||
|
6025981ceb | ||
|
4348e78b24 | ||
|
e2f9adc2ff | ||
|
f67a24499b | ||
|
5c704552d8 | ||
|
d83ea51101 | ||
|
fa6027e8f0 | ||
|
2849191e67 | ||
|
0559eec681 | ||
|
a3a7fe7c8e | ||
|
9b2d176617 | ||
|
7a3547e4d1 | ||
|
e6fb686156 | ||
|
5e80603bbb | ||
|
c8d95a1586 | ||
|
27a99e0a3f | ||
|
3cc351dff9 | ||
|
23c9071c30 | ||
|
14141ec137 | ||
|
5bec2edaf7 | ||
|
f504d0ea99 | ||
|
3b7797b1a1 | ||
|
aa63eb6196 | ||
|
23aa3e4638 | ||
|
56ae3bfec2 | ||
|
4d5c4a13cb | ||
|
69a8f91512 | ||
|
fa791cc344 | ||
|
456f743470 | ||
|
ab6f0012cc | ||
|
4afbf51d32 | ||
|
d62684b617 | ||
|
a8dfcbbfc7 | ||
|
bbdc6210f5 | ||
|
c7f6ed1495 | ||
|
818aa7aeb1 | ||
|
045acc724b | ||
|
d540560619 | ||
|
797bfd85b0 | ||
|
07cb8ebef7 | ||
|
54416cabfd | ||
|
3617ae31f6 | ||
|
4f05d801c3 | ||
|
956afcb33f | ||
|
6347419233 | ||
|
0c7a50fe1e | ||
|
7423932510 | ||
|
b41530ba5d | ||
|
29e916508c | ||
|
b45f3f0004 | ||
|
2a5721b4d4 | ||
|
e30a703c8e | ||
|
333f1a4a40 | ||
|
84b278021a | ||
|
1e470b0473 | ||
|
0ef3a7914c | ||
|
a3fff1e438 | ||
|
4bc204925a | ||
|
5d9946184a | ||
|
5ba169a612 | ||
|
872b37f751 | ||
|
8485136f9a | ||
|
ff1bc739f1 | ||
|
594a0e7f1b | ||
|
8e28ba38d2 | ||
|
73c2ff17dd | ||
|
13f225e6ae | ||
|
3f62492a15 | ||
|
5e3bd2dff1 | ||
|
787a9c74fa | ||
|
14749df6f3 | ||
|
2db2898112 | ||
|
3776000fc4 | ||
|
f0572e59e7 | ||
|
6217184c7f | ||
|
044dcbaed0 | ||
|
8a5eae94ea | ||
|
bf3c6aeed1 | ||
|
f3fbf995ca | ||
|
03bded2b6b | ||
|
d5c0829d61 | ||
|
00369303de | ||
|
1f1479c0a7 | ||
|
e67f848abc | ||
|
560f50d3cd | ||
|
3f45122d0d | ||
|
50bdaa573c | ||
|
24b6698cc9 | ||
|
73885d3b9e | ||
|
f29387316f | ||
|
d6fd0d2aca | ||
|
e814da1eec | ||
|
e029a09345 | ||
|
dcd9c9509b | ||
|
15eb7db36d | ||
|
a5b46bfc8c | ||
|
fbba259933 | ||
|
7b77e2d232 | ||
|
48a182844c | ||
|
9335cdcebc | ||
|
38af93b60c | ||
|
741de6051c | ||
|
b8f0de3074 | ||
|
88d919337e | ||
|
f518b90c6b | ||
|
d5c33e6d6c | ||
|
338eb4ce65 | ||
|
009e208bcd | ||
|
81e6877b02 | ||
|
3722acee85 | ||
|
a4a35f8a4f | ||
|
82119ca923 | ||
|
6ca2019002 | ||
|
53e3463b5a | ||
|
c9ed5f69d7 | ||
|
696d481e3b | ||
|
f5a83ceded | ||
|
3fe66a1298 | ||
|
6af1f65d3c | ||
|
4a10dca7d4 | ||
|
4d57ed314d | ||
|
86d0e12695 | ||
|
4e81bcc147 | ||
|
691baf5b14 | ||
|
6243467856 | ||
|
3c5a4474ac | ||
|
01da65252b | ||
|
f3e7615bef | ||
|
f47a666227 | ||
|
b708db4cd5 | ||
|
a3144e7e21 | ||
|
683efc5698 | ||
|
38a3075025 | ||
|
fc072300ea | ||
|
d25ecfe1c1 | ||
|
37d98e79ec | ||
|
a65605b17a | ||
|
424e59805f | ||
|
6df8111cd4 | ||
|
76db060afb | ||
|
d588532c9b | ||
|
d6d7458d68 | ||
|
228b244c84 | ||
|
d89ecb8308 | ||
|
50751bb610 | ||
|
64f48bf84c | ||
|
f8fdc0cd93 | ||
|
09fe95bc60 | ||
|
ada5941a70 | ||
|
88fe3403ce | ||
|
04f2682ac6 | ||
|
873b5608cf | ||
|
12086744e0 | ||
|
33ab615072 | ||
|
f696d7abee | ||
|
5a1cf19278 | ||
|
416e65509b | ||
|
4de6a78e26 | ||
|
026088deea | ||
|
f142e671b3 | ||
|
2f49b6caa8 | ||
|
50c86919dc | ||
|
781cc00cc4 | ||
|
05dc2b3a09 | ||
|
d0e628911c | ||
|
656633f784 | ||
|
530e1c329d | ||
|
f5aec8add4 | ||
|
f92309bfd0 | ||
|
ef10feb26f | ||
|
c6586829de | ||
|
b103385678 | ||
|
848191e97a | ||
|
04e3fb6a5a | ||
|
b218e17f44 | ||
|
bba6d0c613 | ||
|
49af1f9969 | ||
|
a6dc50e7cb | ||
|
f69b5f7f33 | ||
|
37eac010c8 | ||
|
d4b9f15c0a | ||
|
ec3daedf9e | ||
|
1cf76a10db | ||
|
d83181a2be | ||
|
b834a28891 | ||
|
78f6f6b889 | ||
|
0b02f6593b | ||
|
7f1d9ff543 | ||
|
c5fb734098 | ||
|
d5d3cfd3fa | ||
|
cc77a8c395 | ||
|
d39c273d96 | ||
|
316508626d | ||
|
46ba6a4154 | ||
|
d8cbbc414e | ||
|
ebae491e3f | ||
|
6f919e5020 | ||
|
4ff851b302 | ||
|
3af90f8772 | ||
|
cb54d074b5 | ||
|
9032e271f1 | ||
|
15597aa493 | ||
|
3b9d13fda9 | ||
|
5e0249ae7c | ||
|
27958e4247 | ||
|
353afa7cb0 | ||
|
e865c50574 | ||
|
a30ad1e5a5 | ||
|
586ad89d50 | ||
|
6caa639243 | ||
|
80f31818df | ||
|
854cc53fa5 | ||
|
d2a1ac3b0c | ||
|
a678d1be9d | ||
|
097806dfe8 | ||
|
7cdf1fd388 | ||
|
a4e65c7ceb | ||
|
20ebb49568 | ||
|
aa162b0d5d | ||
|
b15f3e182d | ||
|
4d39c1856e | ||
|
b2fa84af61 | ||
|
913fed0089 | ||
|
80ea18bd28 | ||
|
12c6b5c3eb | ||
|
35c0010876 | ||
|
f52584a715 | ||
|
09bbdadcee | ||
|
d711a0c83f | ||
|
01cf11b961 | ||
|
29825e6873 | ||
|
d18ad63e49 | ||
|
3da392d1cf | ||
|
8947614d97 | ||
|
7e4f4a96fc | ||
|
301a371efe | ||
|
1a6df84c7a | ||
|
2d38c1e20c | ||
|
9155339cf0 | ||
|
d8a023a92c | ||
|
8ad74404c9 | ||
|
1ce2f04f47 | ||
|
20b12751af | ||
|
e485fab7eb | ||
|
adca353fe9 | ||
|
7a72e567d5 | ||
|
3c050be0b0 | ||
|
41e684eb5a | ||
|
2067417ad4 | ||
|
55890e1b82 | ||
|
1e524c68d5 | ||
|
740d8b0a26 | ||
|
a8dd69cf17 | ||
|
4fe2aa6bf7 | ||
|
5d5c9cab19 | ||
|
5f12b7aedf | ||
|
d71590bbd0 | ||
|
9ffc65f8f3 | ||
|
483f1d2ca0 | ||
|
1babba753d | ||
|
ed18a10571 | ||
|
0440e45d65 | ||
|
2fb27c8521 | ||
|
f17f4ff963 | ||
|
e9c34fe038 | ||
|
669ab10c17 | ||
|
0a3cf1a087 | ||
|
3511b55cf5 | ||
|
1f01b6546c | ||
|
0efa3e6392 | ||
|
6d7f3c4405 | ||
|
85e0fb32e6 | ||
|
d0ae316934 | ||
|
f6d280452f | ||
|
7fb5fbac37 | ||
|
b7fd462944 | ||
|
ec08303f82 | ||
|
e640233947 | ||
|
ea7a6f1cf1 | ||
|
38009a215a | ||
|
150a969cf4 | ||
|
3c4cbf133e | ||
|
fd2c47b56a | ||
|
2560c4dda3 | ||
|
254a0ab69d | ||
|
7b3e59ed0a | ||
|
44de04be89 | ||
|
33024731e4 | ||
|
d469282f1c | ||
|
acbf3db233 | ||
|
adf6a7121f | ||
|
b73f009c07 | ||
|
bbfd2dc2bd | ||
|
4fe61968cf | ||
|
9e8e069b23 | ||
|
26ca58419f | ||
|
063faaae1c | ||
|
131c3d4d5b | ||
|
44ee4b507c | ||
|
c36a0226d0 | ||
|
67832aada9 | ||
|
74727b085b | ||
|
bb495006c8 | ||
|
3d25b4dfc1 | ||
|
1c12c19150 | ||
|
58dc641001 | ||
|
88249308a0 | ||
|
b4aaa7b908 | ||
|
c386172be7 | ||
|
c66e9a6d62 | ||
|
81801ce23b | ||
|
7dfa39483f | ||
|
b07641c3f3 | ||
|
4638acfe81 | ||
|
aadef80404 | ||
|
9805fb7a34 | ||
|
7d2ba49969 | ||
|
f81bafa07b | ||
|
94892ab3a4 | ||
|
323d788f48 | ||
|
eafab9636f | ||
|
107bfb259a | ||
|
d4a36aa55b | ||
|
07b2894080 | ||
|
802ac377b8 | ||
|
738ab4239a | ||
|
b5a895d1ec | ||
|
23685b4537 | ||
|
e552be76ce | ||
|
eea22dfd40 | ||
|
0a722942cc | ||
|
192f4c4e96 | ||
|
e03588f431 | ||
|
8872b2e0c6 | ||
|
061f5a313b | ||
|
2e2ed3bd35 | ||
|
7697baf0da | ||
|
22a5a00c49 | ||
|
8b289ad9e1 | ||
|
6a33411d65 | ||
|
9a91ef8628 | ||
|
fbce6349c4 | ||
|
954676b3d8 | ||
|
e2ad6aad5a | ||
|
038a2eb862 | ||
|
5d146e52fe | ||
|
c41c1e771f | ||
|
befa8a6cbd | ||
|
85b77f7c22 | ||
|
6b3f7306a4 | ||
|
ba5c0fa364 | ||
|
2a92fd2f14 | ||
|
7e974f1401 | ||
|
8373fa393a | ||
|
613841381d | ||
|
9e76aafc1c | ||
|
9b5096ab10 | ||
|
01d70f2c7c | ||
|
6878c2af4e | ||
|
db2b76a22a | ||
|
263c8731f2 | ||
|
69e5deeccc | ||
|
2e1e27219e | ||
|
226d5ed7de | ||
|
52e0aa7a80 | ||
|
bd9474bafd | ||
|
316b73178d | ||
|
58c71d8ea6 | ||
|
e245e935aa | ||
|
143e2272ff | ||
|
cd7924f8c9 | ||
|
7f93a5a0f5 | ||
|
1abd3cf3d7 | ||
|
91e2d61cf2 | ||
|
f6d60a7e89 | ||
|
40f1c51ec3 | ||
|
68fd7e39da | ||
|
a096761306 | ||
|
d790ec96d8 | ||
|
5e260fe23a | ||
|
2054a98cf7 | ||
|
ce8ba1f170 | ||
|
595d6427ac | ||
|
39dc61b948 | ||
|
96688269f8 | ||
|
55aa58ee2e | ||
|
556a8d68bc | ||
|
3ed5f89cf5 | ||
|
8d0158ceeb | ||
|
fcd895d032 | ||
|
61d88b8db2 | ||
|
3e52f1a4e9 | ||
|
4479cc48fe | ||
|
5708914699 | ||
|
881be9b741 | ||
|
e6f1c4df7f | ||
|
e2592f1ce2 | ||
|
77d31e679a | ||
|
decbcdc423 | ||
|
e3ffa21303 | ||
|
f2ecda6f0f | ||
|
26f6f1f62e | ||
|
28aee0fc34 | ||
|
f97cb4e761 | ||
|
405198acd0 | ||
|
eecaba6b84 | ||
|
83e11f9ef7 | ||
|
5a7ac7e5c1 | ||
|
c15c933ce8 | ||
|
0697ab4b4f | ||
|
13e3e867ac | ||
|
cc30220f01 | ||
|
257019d424 | ||
|
4959bfc1b3 | ||
|
301671ae19 | ||
|
1e09fd8e0f | ||
|
f10f7d0e84 | ||
|
3ee5aa0d6b | ||
|
fce8712bff | ||
|
2051bf2b67 | ||
|
87c9a871b9 | ||
|
5e2c14e916 | ||
|
5b5546adf1 | ||
|
0b09c8154a | ||
|
bab2e5ed0d | ||
|
7c620ade85 | ||
|
1d9c0c7d17 | ||
|
aa1d5b8970 | ||
|
435993891b | ||
|
1d5a9464e2 | ||
|
e88b8f247a | ||
|
880c9c6b48 | ||
|
7633e6d582 | ||
|
72802e4d8d | ||
|
4fb8adb9e4 | ||
|
5c52a830d2 | ||
|
2c8d75afb7 | ||
|
4d5b41b8db | ||
|
11d9c2e2c3 | ||
|
352fbd71e7 | ||
|
2706633f81 | ||
|
50af3cf6c1 | ||
|
39d7503069 | ||
|
41434ce080 | ||
|
f72ed13f3c | ||
|
0fec370dcd | ||
|
bf63569184 | ||
|
8216e821d3 | ||
|
13efa95ef7 | ||
|
e25237455c | ||
|
b38ed2c959 | ||
|
a34139e19e | ||
|
80379f6cab | ||
|
d58b338bd8 | ||
|
e1e13b68b3 | ||
|
90ee5df413 | ||
|
5834e609a6 | ||
|
532e97c542 | ||
|
d156449819 | ||
|
d4bd08f82e | ||
|
3ce033995f | ||
|
320f4d4d7f | ||
|
16715adfa0 | ||
|
100d972cea | ||
|
ce63597e4a | ||
|
5f117fb65e | ||
|
72fee60c8f | ||
|
1bb1ba2274 | ||
|
6ebcaab2bb | ||
|
cd42e649a7 | ||
|
8167e5b690 | ||
|
de014422bf | ||
|
2f5c0d10bb | ||
|
48b5ee5cd5 | ||
|
dd4159fe65 | ||
|
62a8961d8f | ||
|
e7b835eb4c | ||
|
fbe9e0ac1a | ||
|
40feb120e4 | ||
|
6362211860 | ||
|
925a820b56 | ||
|
50b884a32d | ||
|
890878f5db | ||
|
435ef14379 | ||
|
3c44ffcf80 | ||
|
73aee004ac | ||
|
30a9149b52 | ||
|
4a7f829ecf | ||
|
dc8a8011be | ||
|
5e84dabb46 | ||
|
3e8f4c1545 | ||
|
1a50a1a733 | ||
|
e50647d252 | ||
|
951e4675c6 | ||
|
c04e8b57b9 | ||
|
32d47c836d | ||
|
90a7941d56 | ||
|
3e3ee0aeb1 | ||
|
7b674e0607 | ||
|
593a9a262d | ||
|
456596710e | ||
|
01cd4cf1c6 | ||
|
1712314fab | ||
|
7da9880ff7 | ||
|
d42b37b77d | ||
|
c3e83f464f | ||
|
1550c05a7a | ||
|
ea833a4cd7 | ||
|
2d8e04dca7 | ||
|
d5ce5874e8 | ||
|
225f765b56 | ||
|
ddffdb63bf | ||
|
0d1be39a97 | ||
|
2c1dd69891 | ||
|
145687a48e | ||
|
9051aa5296 | ||
|
432f8e9841 | ||
|
19792cfae7 | ||
|
9463b70edd | ||
|
b109f52dab | ||
|
e0781483fa | ||
|
ffcea384a6 | ||
|
deff6a82fa | ||
|
919a268de3 | ||
|
487cfa5e6c | ||
|
5fcda86f8c | ||
|
f2635776cd | ||
|
d30dbdde23 | ||
|
b59d5c35bc | ||
|
8331f7b056 | ||
|
92274a74f7 | ||
|
1739c479ed | ||
|
551317f1cd | ||
|
ddc19f43ba | ||
|
993b8e2791 | ||
|
9a5438ce2f | ||
|
d33434647b | ||
|
02169e8f85 | ||
|
b07e93e08b | ||
|
bad886ca9b | ||
|
967a042321 | ||
|
a585318b1a | ||
|
07d2f1aa36 | ||
|
b15e685a0b | ||
|
885c6cff71 | ||
|
c5e425b02b | ||
|
3fa81bb86e | ||
|
5daadc022d | ||
|
0cfcd39d55 | ||
|
7875c38023 | ||
|
edfec26988 | ||
|
daa290100c | ||
|
b4eb25197b | ||
|
ac00d23b80 | ||
|
9ae2eefb9a | ||
|
8c18f053aa | ||
|
2aefa25448 | ||
|
6e01c1e377 | ||
|
3c6ee19785 | ||
|
0e2d3fb923 | ||
|
af5e05d08d | ||
|
c83bfc9df6 | ||
|
1ebb670141 | ||
|
9d0786cbb0 | ||
|
53bde23a5e | ||
|
187798086a | ||
|
1540bc9759 | ||
|
618ab93b42 | ||
|
5ba67c55a2 | ||
|
d8ad9aedad | ||
|
3e6d0a50e8 | ||
|
ff09141a14 | ||
|
d188876a91 | ||
|
6f6274d0d9 | ||
|
29ee581067 | ||
|
17f07e2613 | ||
|
9ebdf0e3cf | ||
|
730caa3d58 | ||
|
7deb842030 | ||
|
5f7d5e1e80 | ||
|
931c76e58f | ||
|
3fafa583d1 | ||
|
d8e9b0f675 | ||
|
846c7a26e8 | ||
|
98d766c68e | ||
|
087b7fa38e | ||
|
92877e8bf8 | ||
|
d3ef41b603 | ||
|
633bfa7ebc | ||
|
13af4c1f40 | ||
|
afc3f7dce4 | ||
|
e8901a2422 | ||
|
c888de8b38 | ||
|
fefa1670a6 | ||
|
589d22da0b | ||
|
3dcb914607 | ||
|
b2b421840c | ||
|
5c7eef70b4 | ||
|
c2710899ed | ||
|
b997912ebe | ||
|
e5d07f3a3d | ||
|
fb9155c450 | ||
|
dc3195310c | ||
|
9f7c2b08a5 | ||
|
a6932b6b81 | ||
|
77d705ca9f | ||
|
89ac53acd7 | ||
|
1e22c83f0f | ||
|
1ad1e80ae3 | ||
|
bc785196c8 | ||
|
dfdf530723 | ||
|
33f33a7358 | ||
|
113dd2146a | ||
|
14c2df0418 | ||
|
b316518864 | ||
|
612663667c | ||
|
6c14f35f00 | ||
|
289be0a0db | ||
|
a4de023c29 | ||
|
e3fdd4a0ac | ||
|
bc9e14a762 | ||
|
3c5f20190f | ||
|
9c83551a0e | ||
|
99c139dd5a | ||
|
6c34745958 | ||
|
2ba4e9bda5 | ||
|
2a00c931e4 | ||
|
1e6ad5acb6 | ||
|
bc74a37696 | ||
|
0cb326b10f | ||
|
4daa9aa443 | ||
|
667364143c | ||
|
d8b357ce49 | ||
|
479d0e858d | ||
|
152c15b19f | ||
|
ce5a34d86c | ||
|
b8bafb2893 | ||
|
5da18854a3 | ||
|
d269e7f46c | ||
|
8c636f67af | ||
|
a84508d6b9 | ||
|
22c234040e | ||
|
4a1be18361 | ||
|
3b6df70f11 | ||
|
48390d37c2 | ||
|
0d3beb4e5a | ||
|
6e192d487b | ||
|
306c61a968 | ||
|
58b4fea2b1 | ||
|
2149bfbc5b | ||
|
0acb823d96 | ||
|
8ba6b601b0 | ||
|
06f981ffed | ||
|
4a4a3f759c | ||
|
8fbebf4e83 | ||
|
8371beb915 | ||
|
b39b32a48c | ||
|
dbe99b59a7 | ||
|
3cc413fe9a | ||
|
59d0138bcd | ||
|
801bbcbc63 | ||
|
4560ff7386 | ||
|
477841d8c0 | ||
|
a89dc49c52 | ||
|
90d8f7aa6a | ||
|
abc1421def | ||
|
7abd4eeafd | ||
|
27c79088e6 | ||
|
ce2a3a80db | ||
|
79bf74e90f | ||
|
4f12ba00d1 | ||
|
93104d9224 | ||
|
b5f4a79365 | ||
|
7e84de2ae1 | ||
|
06e1f81801 | ||
|
ccc3f89060 | ||
|
8a17de327e | ||
|
3b787123e3 | ||
|
127969d65f | ||
|
4b711e29ef | ||
|
2a3aa591e0 | ||
|
56cafc3fb3 | ||
|
b434456f54 | ||
|
6923d350f4 | ||
|
38beab8fe8 | ||
|
4bdd0ce417 | ||
|
e5c4e1ecc3 | ||
|
a48131f1e1 | ||
|
6e34918b52 | ||
|
66fddb2d52 | ||
|
87193fd270 | ||
|
52b5309385 | ||
|
7f4e048052 | ||
|
7fe7357154 | ||
|
635261eb12 | ||
|
5a5cf15c04 | ||
|
4d2b6b71f2 | ||
|
7bec169d58 | ||
|
bfd4ccbeaa | ||
|
76fe84fe93 | ||
|
cf4dd645a7 | ||
|
a5edd0d709 | ||
|
c33e08c3fa | ||
|
9b773185c3 | ||
|
b1974ab3cf | ||
|
b4e2b85745 | ||
|
fcd8d850dc | ||
|
6549b8f8ae | ||
|
1ea7ec3189 | ||
|
4077934519 | ||
|
fac8aaa44e | ||
|
fd422a0646 | ||
|
d7bb4d954a | ||
|
36322901a6 | ||
|
31d8fc086b | ||
|
9ca583d984 | ||
|
3ce933051a | ||
|
3b750cafc1 | ||
|
1911fe5ca8 | ||
|
2117e8167d | ||
|
c66d1ad6cb | ||
|
bd0383a4e3 | ||
|
dd5327ef9e | ||
|
cdce8c81da | ||
|
3f786542d3 | ||
|
e813b26963 | ||
|
abe711dcb5 | ||
|
b35a9fcb04 | ||
|
c27a91f7f0 | ||
|
2ab2f3a0a3 | ||
|
c825f4d180 | ||
|
7e195b06a6 | ||
|
30132d8c35 | ||
|
0d89db5141 | ||
|
4b7d59224d | ||
|
72157a7514 | ||
|
4f51607145 | ||
|
6602760a48 | ||
|
9232261665 | ||
|
af97febb04 | ||
|
c818dc1ce8 | ||
|
05dabb7e7b | ||
|
ad50f376a5 | ||
|
66e304c41b | ||
|
192f7967c9 | ||
|
f67d82a9db | ||
|
3cfbc1a79a | ||
|
d9f495d391 | ||
|
71f6c018ce | ||
|
0401f4afff | ||
|
b4989b5a2a | ||
|
6f4054679e | ||
|
df7d53b9ef | ||
|
0a9a42b544 | ||
|
0232e755f3 | ||
|
0536125f75 | ||
|
53d87e53c5 | ||
|
232020ef96 | ||
|
a22d74b165 | ||
|
8b8e534769 | ||
|
6b71229d3f | ||
|
145e5c8943 | ||
|
28315ca933 | ||
|
dced082e5f | ||
|
408faac3c9 | ||
|
cd4a606cb1 | ||
|
c7c3effd6f | ||
|
36898a2c39 | ||
|
8526c30b63 | ||
|
d6ebe8c3e7 | ||
|
02de35cfc3 | ||
|
7d8e21634c | ||
|
6b598eaacb | ||
|
2197330727 | ||
|
1d8627eb8b | ||
|
8f85ea89fa | ||
|
51a5f54fc4 | ||
|
e5550b5140 | ||
|
a1d6078d46 | ||
|
7fd87b95cf | ||
|
e3d562bcdb | ||
|
442e6e55b6 | ||
|
1f1a87bd3d | ||
|
4d1055f5d5 | ||
|
68acdd71f1 | ||
|
62b1ea2b48 | ||
|
9fa23ffa21 | ||
|
1dda89dbe3 | ||
|
2a1f77efc6 | ||
|
f9502e0964 | ||
|
09b67c1ad5 | ||
|
66475f98b9 | ||
|
8512cc5cca | ||
|
3a65c66a3e | ||
|
492b3e525d | ||
|
639010b3df | ||
|
34d1f0bff2 | ||
|
a330b281e8 | ||
|
6f9f80acee | ||
|
a8a62afd74 | ||
|
7fa682bdd5 | ||
|
34019291b8 | ||
|
847390dd9c | ||
|
08179018d4 | ||
|
b796226869 | ||
|
131d565498 | ||
|
084af7b6e5 | ||
|
bacd8c70e1 | ||
|
963c3479a9 | ||
|
39c567de47 | ||
|
da4cc74498 | ||
|
cac485756b | ||
|
118a7cd4ae | ||
|
c058e7a5ec | ||
|
1c10c3e2ff | ||
|
e0ddabc463 | ||
|
13da9bf75e | ||
|
e47eeb67ee | ||
|
824199fc7f | ||
|
c004896a40 | ||
|
940d2fdbb1 | ||
|
1c999b2a61 | ||
|
8e37841a2e | ||
|
8d1c0c469c | ||
|
8f5b0c777b | ||
|
0dd82293f1 | ||
|
26d7380c2e | ||
|
95703fb6f2 | ||
|
0121bce9e5 | ||
|
e766dd5582 | ||
|
fb1678d425 | ||
|
884053aaa7 | ||
|
93429bc661 | ||
|
3d27007750 | ||
|
4cbd97667d | ||
|
2730c90dcd | ||
|
09a1bcb30b | ||
|
77e08ba204 | ||
|
d3adf09bde | ||
|
26db1afd1a | ||
|
afa2a5f1c4 | ||
|
bcaf2f9ea3 | ||
|
3cd38e0d4c | ||
|
d16b562b18 | ||
|
0538f8a70d | ||
|
1a426ada3c | ||
|
d96e17451e | ||
|
a544e54578 | ||
|
f34a6699ef | ||
|
482857611a | ||
|
8d8bbc294a | ||
|
7f91f6e034 | ||
|
84c4c7dc82 | ||
|
1d4aa7abcc | ||
|
fe35c32c62 | ||
|
aa0da221e9 | ||
|
f1403493df | ||
|
36901d8394 | ||
|
a789707027 | ||
|
e6a2e34dd1 | ||
|
934d92f09c | ||
|
016ba4cdfa | ||
|
b227e44498 | ||
|
5e59541faa | ||
|
d94b7fd57c | ||
|
9964ba77ee | ||
|
153661cc47 | ||
|
166da2ffd0 | ||
|
8becd905b8 | ||
|
c83350e597 | ||
|
730866f431 | ||
|
ffbe9e7fd8 | ||
|
91b02c057e | ||
|
55d76ea3d8 | ||
|
1df0b67ec1 | ||
|
cd3b30d3bf | ||
|
53a685dbf8 | ||
|
218e527363 | ||
|
27fc391f71 | ||
|
1091e82327 | ||
|
a5cc8537f9 | ||
|
d692737a13 | ||
|
cc79125d3e | ||
|
a801e02cea | ||
|
29c7775ea1 | ||
|
cbf099de4d | ||
|
c8630f46fd | ||
|
af74d85b7d | ||
|
b8e7b4c0cd | ||
|
97e5f28537 | ||
|
f42e0a4711 | ||
|
6a5c828b6c | ||
|
97aa87612a | ||
|
d91f9e14e6 | ||
|
e24b1220a0 | ||
|
18f0531bba | ||
|
0a720b35af | ||
|
f557b54489 | ||
|
04852ad753 | ||
|
ee4f437aa2 | ||
|
aaa9a4efac | ||
|
0140cf71c8 | ||
|
51794e4c13 | ||
|
b249b06036 | ||
|
20caaf9d1f | ||
|
cb133cba68 | ||
|
c41ca22a78 | ||
|
009d2ffc6c | ||
|
baf1aba239 | ||
|
b891d77679 | ||
|
1d2ae39cff | ||
|
7bf09945f2 | ||
|
5c2e9a5376 | ||
|
b3a689658b | ||
|
d182d4f979 | ||
|
9c49e071d3 | ||
|
0f63924ed4 | ||
|
b2a7a27dfb | ||
|
b79dd602f3 | ||
|
157639e451 | ||
|
ea2c9d8f57 | ||
|
f958b32c83 | ||
|
2faa8f1e37 | ||
|
ab462d92b8 | ||
|
27905bbddf | ||
|
dc3e317d20 | ||
|
ac87ba5c0d | ||
|
ea918e1999 | ||
|
a5509fc2ce | ||
|
b614a3504b | ||
|
661d455ab4 | ||
|
cd8e469b9c | ||
|
991b3dbe54 | ||
|
a3caeba242 | ||
|
f5251f7d27 | ||
|
faedfb6307 | ||
|
1940495817 | ||
|
b979fb0116 | ||
|
7e140e5f3c | ||
|
0e5393f203 | ||
|
df6cf9aa51 | ||
|
5cf1396cb7 | ||
|
435e098751 | ||
|
6ffddbff24 | ||
|
64b0ce974d | ||
|
ce776f0f6a | ||
|
949984601f | ||
|
055e80f846 | ||
|
15363530ae | ||
|
ca6c5e2a6a | ||
|
73ddb62c58 | ||
|
a512f68650 | ||
|
83838b7fbc | ||
|
769f99b369 | ||
|
bf1b9649d0 | ||
|
6569180654 | ||
|
ae0ed87c0f | ||
|
9cc8ef4b91 | ||
|
ad33f71ac2 | ||
|
30634b3a25 | ||
|
b31cf0284d | ||
|
50c6a98b15 | ||
|
e7234c9114 | ||
|
a644b7c267 | ||
|
f0af7262b1 | ||
|
0865bef382 | ||
|
8c9588ab59 | ||
|
c0ce875743 | ||
|
a22d28e1c1 | ||
|
c32145057d | ||
|
fbb98b0070 | ||
|
db11394711 | ||
|
72f6b3f836 | ||
|
0a08268efb | ||
|
ccda9664e7 | ||
|
e98ba9e839 | ||
|
fd57fde075 | ||
|
6204b85a37 | ||
|
9fc8f9a07d | ||
|
8745486fb3 | ||
|
7cbe3c2171 | ||
|
a47c9239e8 | ||
|
635ca1a0b8 | ||
|
32fdfbcd5a | ||
|
dee9324d4b | ||
|
df8b27c03c | ||
|
8e95974930 | ||
|
64b32146ca | ||
|
36a7bdfac1 | ||
|
13dda0e36e | ||
|
6e7100f283 | ||
|
059cd17b47 | ||
|
fb7b3305dc | ||
|
0e1f24e95a | ||
|
81c3f2c971 | ||
|
82a28d6bb3 | ||
|
22f9114630 | ||
|
1704d699c4 | ||
|
f2f0cdd0ff | ||
|
da06c8e5a9 | ||
|
2f1fe44762 | ||
|
19268ded23 | ||
|
f67933d2ac | ||
|
247b9e83d8 | ||
|
9c2098b8fa | ||
|
48c0c8d854 | ||
|
f5f7b1626b | ||
|
c87a373c53 | ||
|
2609ec0dc3 | ||
|
61ed9886c1 | ||
|
aafd034ab8 | ||
|
d14394c691 | ||
|
16fc22a207 | ||
|
d9ea937493 | ||
|
a96a0ee307 | ||
|
f48468b83b | ||
|
5b79ec8e3b | ||
|
3f4acbc5f6 | ||
|
35e5adaf0a | ||
|
a268a49e1a | ||
|
91a83a3a0f | ||
|
a247c2c713 | ||
|
4feb62f6bf | ||
|
ac4ef719cc | ||
|
ceb97e5809 | ||
|
3bfda55fca | ||
|
9eade647e6 | ||
|
f82a1933b0 | ||
|
bbdd1c8f06 | ||
|
f876c89081 | ||
|
1babbcca85 | ||
|
58ecd312a7 | ||
|
c0dfa72707 | ||
|
fe1e758856 | ||
|
f325d13082 | ||
|
52ab54eeea | ||
|
d407a590a6 | ||
|
5eb805f098 | ||
|
dfdcb56784 | ||
|
659cccc507 | ||
|
f47c31dce5 | ||
|
236f066635 | ||
|
5ab8a712d9 | ||
|
cf7b9cfeef | ||
|
6090af29e7 | ||
|
359009bb05 | ||
|
bdbfa4d403 | ||
|
6849788ebc | ||
|
ac639b2a17 | ||
|
b18ed5922b | ||
|
b395bb953f | ||
|
b652792a93 | ||
|
7efe287c74 | ||
|
881b46f458 | ||
|
d43cd9a24c | ||
|
fff48d24ea | ||
|
f4feb17629 | ||
|
33135f2ada | ||
|
d6f4d10075 | ||
|
f97515352b | ||
|
f765ed8f1c | ||
|
84bfcbc0d8 | ||
|
2c98efb781 | ||
|
f7f58bf070 | ||
|
1432e511a2 | ||
|
1ddc420e39 | ||
|
b61eb7d7f3 | ||
|
dd55458315 | ||
|
1567a977c3 | ||
|
cb8be37f72 | ||
|
e5dd4e1e70 | ||
|
6d74a3db7a | ||
|
1da5926a94 | ||
|
4882531c29 | ||
|
f59b80b80b | ||
|
f7d0e4208e | ||
|
7b61a0eff0 | ||
|
23fd3461bc | ||
|
e22e15afda | ||
|
f453567cce | ||
|
69786b2d16 | ||
|
5a4352657d | ||
|
f13bc796d9 | ||
|
7a2cfb8578 | ||
|
a6a14e7f77 | ||
|
80cfeea957 | ||
|
2c90208486 | ||
|
4eea7f7eb9 | ||
|
3c59657f59 | ||
|
6598beb804 | ||
|
32049efbc2 | ||
|
78be27e18f | ||
|
5d9908c2c3 | ||
|
7eb4d7bb19 | ||
|
a7b0c454db | ||
|
83e3b72220 | ||
|
7e2e3ddd32 | ||
|
c3b3572025 | ||
|
f897596844 | ||
|
6df71956c4 | ||
|
94df70be98 | ||
|
6650bc6b25 | ||
|
7398858572 | ||
|
0c0a2138d9 | ||
|
5bf152886b | ||
|
08353f291b | ||
|
497db69c9f | ||
|
c7de737551 | ||
|
69749a5b7b | ||
|
b3e32c1393 | ||
|
fc38b6d0ca | ||
|
c34900e569 | ||
|
855f2a55cb | ||
|
ea35e6be9b | ||
|
71fdc257bc | ||
|
fd16f77e20 | ||
|
3eef8dc8d0 | ||
|
59176ebbb9 | ||
|
3663061b38 | ||
|
b421d0ed5b | ||
|
f7097fbe07 | ||
|
35efc387c4 | ||
|
fb309ca446 | ||
|
c833a8872b | ||
|
1d4f88eea8 | ||
|
e9b8c8956d | ||
|
095ccef8bd | ||
|
0df969ad19 | ||
|
3e5b6a5481 | ||
|
3201f17058 | ||
|
c36744e96d | ||
|
e51c5dc0a6 | ||
|
d297b82e82 | ||
|
ca649b57e6 | ||
|
2c587f9ea5 | ||
|
98b818bbaf | ||
|
26bf719a02 | ||
|
7e37aa4aca | ||
|
ce6854e726 | ||
|
ac49bbb336 | ||
|
b490231f59 | ||
|
6c7eabb53b | ||
|
7a0f0126f7 | ||
|
59d89a37cc | ||
|
1a07c87af7 | ||
|
29894293eb | ||
|
4d783fff0d | ||
|
a7a53d1f38 | ||
|
7f16b46ed5 | ||
|
58ee5f1cc9 | ||
|
bc844ca96e | ||
|
253dc4f606 | ||
|
b54ce3e66e | ||
|
a642931422 | ||
|
2228f0dabc | ||
|
a619dfb03e | ||
|
54548d3b95 | ||
|
58d4d65fab | ||
|
364ab2a6b7 | ||
|
fdbb078aa9 | ||
|
2ffc1afe40 | ||
|
18612b3501 | ||
|
d635a97088 | ||
|
9da5d67728 | ||
|
bd413e36a3 | ||
|
2c5781ace1 | ||
|
b50b3430be | ||
|
0e3518f2ca | ||
|
238f04c931 | ||
|
3a85a2f81c | ||
|
5dbfa0384e | ||
|
80c87db148 | ||
|
d0d7777d68 | ||
|
48b6128814 | ||
|
70b28288a3 | ||
|
a11e1eba9e | ||
|
2dfa928c90 | ||
|
d3c0fe1fcb | ||
|
36e8683cf5 | ||
|
c0221c2e72 | ||
|
9cef20187c | ||
|
95f1e4634a | ||
|
581a30fdec | ||
|
19e2868484 | ||
|
8b3ce6e418 | ||
|
d8e77600e2 | ||
|
e3dcd96301 | ||
|
001cae5894 | ||
|
494ff9522b | ||
|
53aee6dc24 | ||
|
fd380615a0 | ||
|
039180b2ca | ||
|
22b89edbbc | ||
|
4650f04b37 | ||
|
9fba448053 | ||
|
82f9652fd8 | ||
|
94ae945bea | ||
|
f6189885c2 | ||
|
5c039d87aa | ||
|
08dfb7b59f | ||
|
4c0e723ead | ||
|
ea6af449a8 | ||
|
f72d74f951 | ||
|
d285565475 | ||
|
4eadf3228e | ||
|
99c5aa5a02 | ||
|
6ed65d762b | ||
|
ac18f6cf8b | ||
|
1f7a42f3a4 | ||
|
e71f261935 | ||
|
fcfe12437c | ||
|
b902602d16 | ||
|
b1ef336ffa | ||
|
d284961d47 | ||
|
8ac57201a7 | ||
|
538cb3b1bd | ||
|
17e335c6a7 | ||
|
280d6cac1a | ||
|
c288ffc55d | ||
|
9075dbdd3c | ||
|
16bd0d2b5d | ||
|
7850bce254 | ||
|
3d19e03294 | ||
|
496cb306bc | ||
|
b1f8bfdf7c | ||
|
2c38e4e1ac | ||
|
411d07a4f6 | ||
|
7d3a6541d7 | ||
|
0f400a113c | ||
|
e8447e3d71 | ||
|
f086b6824e | ||
|
ac644ed049 | ||
|
453fea1977 | ||
|
a953f1ca8b | ||
|
4b5cb1185f | ||
|
275cdc1ce3 | ||
|
8d6f67e476 | ||
|
9172150966 | ||
|
1f2831967e | ||
|
c19643cee2 | ||
|
a5c165bb13 | ||
|
d43f09081e | ||
|
1385091768 | ||
|
e30847e231 | ||
|
72074f283b | ||
|
a5db3dbea9 | ||
|
a2c9331b56 | ||
|
1a38a9df88 | ||
|
9b349a9049 | ||
|
329e97c4d3 | ||
|
2bd8fbb2dd | ||
|
205ea33b10 | ||
|
c42397d7db | ||
|
0366600b45 | ||
|
6a4ce96b7d | ||
|
b61c64a8ea | ||
|
ca62c75bdf | ||
|
38bd328abb | ||
|
37ccf7e405 | ||
|
cb91003cea | ||
|
4ad7b229d3 | ||
|
97e0de7e29 | ||
|
83d1486a67 | ||
|
9081b3f914 | ||
|
cf445fd4fe | ||
|
72f053d9bb | ||
|
a0defefb3f | ||
|
9e19159547 | ||
|
62b1166911 | ||
|
810596c6d8 | ||
|
a488d55c2c | ||
|
8106f1c86d | ||
|
306a6a751f | ||
|
318c69350e | ||
|
e63bc65a9d | ||
|
d306c9708c | ||
|
6a65345ef3 | ||
|
f1e348ab95 | ||
|
1a3b9dd864 | ||
|
8fee1ab102 | ||
|
5c617c5a8b | ||
|
6d1804d8a4 | ||
|
ee67ece641 | ||
|
0b939a495b | ||
|
4d7426ec95 | ||
|
f703814561 | ||
|
c39835628d | ||
|
1253725975 | ||
|
f4c1d6a5d7 | ||
|
d7abdced05 | ||
|
78aeef074e | ||
|
0b7aa33bc2 | ||
|
5a4f07adca | ||
|
4092f96dd8 | ||
|
effd27a5f6 | ||
|
fa003af8f0 | ||
|
77c870b7d0 | ||
|
32a6ca4fd6 | ||
|
958eca2863 | ||
|
af635ff3ff | ||
|
728024e8ff | ||
|
b548f6f320 | ||
|
62df6ac724 | ||
|
8bcad4f5ef | ||
|
31e6c44b07 | ||
|
77c910c1c3 | ||
|
c20196f9a0 | ||
|
f6a15b1829 | ||
|
7c22def422 | ||
|
87e49f0055 | ||
|
a36e3fbec3 | ||
|
4bceaf77ee | ||
|
35a3597416 | ||
|
2a279e30b0 | ||
|
b900bd6e94 | ||
|
c685dc493f | ||
|
aacc89e4e6 | ||
|
8e275ab2bd | ||
|
e24f888bc4 | ||
|
b56f465145 | ||
|
74cad6b811 | ||
|
3d2ea28c96 | ||
|
a260412c7e | ||
|
8ef0cf771f | ||
|
9516170ce5 | ||
|
5aefa847df | ||
|
831ef7ea2c | ||
|
9c7e30e4b4 | ||
|
8c5bfc7718 | ||
|
61046a6923 | ||
|
9d2fabc9b9 | ||
|
a643f72d93 | ||
|
73a2a18006 | ||
|
2ef05fb3b7 | ||
|
e06d02365e | ||
|
d6f2dbc723 | ||
|
20dba8b388 | ||
|
f624ba47fb | ||
|
94aa062d51 | ||
|
c0935e161b | ||
|
70fbc01cc1 | ||
|
6c2f169ea2 | ||
|
c230e617f0 | ||
|
1aee6ec371 | ||
|
d3fdfee211 | ||
|
3232e2743e | ||
|
cbb959151c | ||
|
c3d8b131db | ||
|
236d1a448d | ||
|
cfd51b1ac7 | ||
|
61e97251a5 | ||
|
c192a01b20 | ||
|
3ad9e9c5eb | ||
|
97a05ff34a | ||
|
6aaaf4a272 | ||
|
cd64f41524 | ||
|
df279b1ff6 | ||
|
aa859bc640 | ||
|
6ac601fd2d | ||
|
3a569c9dcb | ||
|
27d62941b2 | ||
|
ab345c5f69 | ||
|
a06f641b6c | ||
|
f2f1e7f9d1 | ||
|
0686b8452e | ||
|
72504d26dc | ||
|
1e98e8444e | ||
|
f216e7339b | ||
|
291dd1aca8 | ||
|
38da0adead | ||
|
81b3343796 | ||
|
f2c160e7e0 | ||
|
3d819a6edd | ||
|
20bd656975 | ||
|
cfe939ff08 | ||
|
9f245dd9b2 | ||
|
cf8e9eed69 | ||
|
10c9fe96b0 | ||
|
42b24616ac | ||
|
f9ccb93825 | ||
|
daeea75fbb | ||
|
0ad0202e8f | ||
|
a2a26755fe | ||
|
1f02cc70f1 | ||
|
fe010504aa | ||
|
05e3c76b1d | ||
|
63a458063b | ||
|
a8715f9f0f | ||
|
59be578842 | ||
|
cb0a257349 | ||
|
1081f620d2 | ||
|
e1cfe83825 | ||
|
6019a84fb3 | ||
|
f4d762bb95 | ||
|
69ea28e187 | ||
|
2f5a9e180c | ||
|
f912a4ece5 | ||
|
d1e66f9cc8 | ||
|
1a25903583 | ||
|
0728a2a78a | ||
|
b67cf74c5e | ||
|
2832a1cdcd | ||
|
4e0ed1ea50 | ||
|
164122555d | ||
|
11d87ecc37 | ||
|
7433348aae | ||
|
3673ed6262 | ||
|
16f860bbc2 | ||
|
d973ecf5cc | ||
|
f88cd27686 | ||
|
2a4fc70e1c | ||
|
c9c12129fd | ||
|
38f7ba2584 | ||
|
c4b1808983 | ||
|
f3ed740a75 | ||
|
b3f9cae820 | ||
|
a67bdff28c | ||
|
e3c8b230a0 | ||
|
9689a28d15 | ||
|
095d33bc51 | ||
|
821966b319 | ||
|
ab46687a8a | ||
|
be7278ce9d | ||
|
428218dbf0 | ||
|
d110999d31 | ||
|
4b8daa22f6 | ||
|
3f1887316b | ||
|
e60a63ea51 | ||
|
a2a7bcd43d | ||
|
c1bc4615fe | ||
|
76dca877da | ||
|
38e727dbe1 | ||
|
eba486f229 | ||
|
4ac79993e2 | ||
|
7c93e71801 | ||
|
1be399ab7b | ||
|
eae4fa040a | ||
|
a3c53efaf7 | ||
|
0f7fefd1b5 | ||
|
76fc786c07 | ||
|
76a1fd37ff | ||
|
73800ef111 | ||
|
742a8782dd | ||
|
8f6c863d7b | ||
|
cd7c58e8d3 | ||
|
a1de8a07d6 | ||
|
476b14b06e | ||
|
49d106f615 | ||
|
63fdfae918 | ||
|
ad48606e4e | ||
|
32f312f4a6 | ||
|
52ffd5dae4 | ||
|
c75da43f22 | ||
|
65f14f636d | ||
|
d7d85d2d3e | ||
|
363627d9f8 | ||
|
322b528ee0 | ||
|
0fe5f120a3 | ||
|
7950a49e28 | ||
|
698da78768 | ||
|
ba320e918d | ||
|
07cc981971 | ||
|
e23fd5ca44 | ||
|
7df5edef52 | ||
|
1eaa6925b9 | ||
|
86212d59ae | ||
|
82deb2c57f | ||
|
7507031cb1 | ||
|
51a9379d3c | ||
|
d73d60c9b0 | ||
|
004b4a0436 | ||
|
67ce8925e4 | ||
|
3a1f6810b7 | ||
|
066016cd3e | ||
|
28d6eb6af1 | ||
|
1a47a9b850 | ||
|
addd67dc63 | ||
|
70e0998a70 | ||
|
988bd88468 | ||
|
0d88972d3e | ||
|
0e012e5987 | ||
|
595e96ebf1 | ||
|
4c81cd2a71 | ||
|
32a8ea8094 | ||
|
c594bd7feb | ||
|
223ed98828 | ||
|
39e3df25a3 | ||
|
0fb017b9c1 | ||
|
fb465f8b4b | ||
|
3501eb6916 | ||
|
00db751646 | ||
|
df6c5b28a1 | ||
|
59789ae02a | ||
|
414e420bd2 | ||
|
03de4c0806 | ||
|
4fb8e6d455 | ||
|
06cdb260f6 | ||
|
c3c5817af6 | ||
|
9168c71359 | ||
|
1a14f1ecc1 | ||
|
44cb126e7d | ||
|
51f4e6585a | ||
|
f81e6d2ccf | ||
|
80dd230a65 | ||
|
d1b4ea5807 | ||
|
f5db403c45 | ||
|
75950344fb | ||
|
a49e06b54b | ||
|
0945eb990a | ||
|
a498cc223b | ||
|
ddd200bbfa | ||
|
9707aa8091 | ||
|
2e6a260ab1 | ||
|
49c6bf8fa6 | ||
|
296b92dbd4 | ||
|
b2756d148a | ||
|
756af57787 | ||
|
cb7096f2ec | ||
|
3c4871d9b8 | ||
|
f90673ac68 | ||
|
d435e17681 | ||
|
23e9737b85 | ||
|
54beb27eaa | ||
|
7968437a65 | ||
|
693b7c5fd0 | ||
|
1bd49ff125 | ||
|
9f460dd1bf | ||
|
2441dd6f6f | ||
|
ea44ad4d75 | ||
|
4b4786f75d | ||
|
02cd5418c2 | ||
|
c432697667 | ||
|
c7683f33cb | ||
|
49e3665d96 | ||
|
e95ba800ea | ||
|
5d9bb300d7 | ||
|
afcd5997b9 | ||
|
f73717ea35 | ||
|
1967963702 | ||
|
76dd0cd777 | ||
|
d87b6fd9f3 | ||
|
a6a47dbc96 | ||
|
61791bbb3d | ||
|
298c6cb790 | ||
|
a561ee6207 | ||
|
3fa7468d54 | ||
|
bc3abad602 | ||
|
d75b5d6931 | ||
|
02bf742e15 | ||
|
d07f75b389 | ||
|
2d34781259 | ||
|
cdb63a8c49 | ||
|
44a0626fc8 | ||
|
45eac53ec7 | ||
|
e42203a13e | ||
|
4ba25326ed | ||
|
dca4777347 | ||
|
e113d1ccab | ||
|
112ccfa9db | ||
|
0ed1919a38 | ||
|
ff003cfa3c | ||
|
6c954df636 | ||
|
981e61fb51 | ||
|
5db1c3eef7 | ||
|
3535c29e59 | ||
|
88765f62e6 | ||
|
0f35e17e23 | ||
|
77b3f9bb97 | ||
|
09f93d9e0c | ||
|
45f15bf753 | ||
|
913cc5a9af | ||
|
a46acfcdd8 | ||
|
0c0f6b755d | ||
|
94eb18b3d9 | ||
|
af5943f7e6 | ||
|
ecda4e3a8c | ||
|
4c12b273ac | ||
|
b68854f79d | ||
|
f954bc0a5a | ||
|
7b8359df4d | ||
|
66b61866cd | ||
|
3736bfa04a | ||
|
dfc46f02d7 | ||
|
9086665013 | ||
|
0210e53bb7 | ||
|
ca40d51bc6 | ||
|
ca6a07f595 | ||
|
b5bd959a97 | ||
|
f26e16bf79 | ||
|
973e7372b4 | ||
|
b54e091886 | ||
|
6c220e4e4b | ||
|
2511e14289 | ||
|
0f5ea5474c | ||
|
6567b8e012 | ||
|
aee3ec682e | ||
|
428a554ddb | ||
|
32f4194cf8 | ||
|
6f3ff70b17 | ||
|
76bb5f8d75 | ||
|
4b98537f79 | ||
|
cac2196ad5 | ||
|
ba24fe3226 | ||
|
3004791c64 | ||
|
b1a7889ff5 | ||
|
86e3506ae6 | ||
|
92fc2df214 | ||
|
4f714b07b8 | ||
|
eb4038a6b9 | ||
|
4c0e9ba890 | ||
|
deac627dc7 | ||
|
6ee3c053b7 | ||
|
16961f69f2 | ||
|
b9b028a735 | ||
|
5fe144aa0f | ||
|
5b0da4279f | ||
|
1ac978b8fa | ||
|
c1a2e9a8c6 | ||
|
195d6d791a | ||
|
aa301c31d1 | ||
|
d9418b1dc4 | ||
|
2c89a02db3 | ||
|
0ca08e03af | ||
|
15efdf0c16 | ||
|
ab8760cc83 | ||
|
b6da596ec1 | ||
|
3c12c6beb3 | ||
|
26caad4f12 | ||
|
8ece922ef0 | ||
|
887a468d32 | ||
|
859a7f32fb | ||
|
1f28764ca1 | ||
|
76cb37d6b5 | ||
|
7ddd4cd38c | ||
|
c1eb975545 | ||
|
414b739641 | ||
|
572ab650db | ||
|
e296ccb4d0 | ||
|
72c2a8982b | ||
|
13c57147eb | ||
|
7e58b96328 | ||
|
ac4a71452e | ||
|
03bcfa7ff5 | ||
|
af5f376163 | ||
|
004b0a3fcf | ||
|
4bb7d2b566 | ||
|
94a0562c93 | ||
|
f619eb08b1 | ||
|
55195fe546 | ||
|
5711074c5a | ||
|
4a705b3fba | ||
|
31e386886f | ||
|
4d85e3765e | ||
|
f0a04b4d65 | ||
|
760ca1c3a9 | ||
|
23b3833806 | ||
|
daeeae1a91 | ||
|
c8f857eae4 | ||
|
270d21f5c1 | ||
|
bf29198efd | ||
|
db4e225342 | ||
|
9ebbf1c3cd | ||
|
ef7f5edbb3 | ||
|
0b5404b2b7 | ||
|
19e1b11d98 | ||
|
0df32b03ca | ||
|
72a4223884 | ||
|
03117d9572 | ||
|
c78f5393c3 | ||
|
fda49564bf | ||
|
ed48b6e4b7 | ||
|
848fc323db | ||
|
e6f57f27ee | ||
|
015ea62e92 | ||
|
2ca7087018 | ||
|
d665f14682 | ||
|
e375678674 | ||
|
076b5c153f | ||
|
d33a482c91 | ||
|
d64839e7d2 | ||
|
31705a502d | ||
|
5f5d0ffe14 | ||
|
4f7479d94d | ||
|
9511178666 | ||
|
b8d1652baf | ||
|
f7dc73b830 | ||
|
8eac37fabd | ||
|
1d0415a6cf | ||
|
3f5c60886b | ||
|
a75598b3f4 | ||
|
60a057cace | ||
|
dd9d0c0530 | ||
|
9fa995ac9d | ||
|
f07734596e | ||
|
caec3de364 | ||
|
60bfc56e8e | ||
|
206e24448b | ||
|
4175431dcd | ||
|
bb1eb9fec8 | ||
|
b0d7115e9b | ||
|
f8ebd08e75 | ||
|
6ac7840195 | ||
|
30e4b89837 | ||
|
405c711edb | ||
|
0e6b4e80f7 | ||
|
9949782e96 | ||
|
bbb6e7b3da | ||
|
bc68188209 | ||
|
d3780e181e | ||
|
2e202051e3 | ||
|
448c1d5faa | ||
|
ff2b8e5e60 | ||
|
8b71ef8ceb | ||
|
ee8f678010 | ||
|
6425c837d5 | ||
|
a6b918c1a1 | ||
|
c025ab4eb4 | ||
|
ae30009fbc | ||
|
158d775306 | ||
|
9d540165c0 | ||
|
0cb51e7530 | ||
|
13e47e73c8 | ||
|
6c4e5e0e3d | ||
|
d2fd7b7462 | ||
|
d9453f323b | ||
|
b787b76c6c | ||
|
a94a407a43 | ||
|
96e46c4209 | ||
|
aa30fa8009 | ||
|
ebfee51aca | ||
|
8b6a6a5a28 | ||
|
14ac7d797b | ||
|
f253691a68 | ||
|
038da7255f | ||
|
73cd24bf5a | ||
|
4ee9cb2be9 | ||
|
f1d2f84043 | ||
|
b9a949820a | ||
|
50e5f0d28b | ||
|
1481f7d64b | ||
|
7d33650019 | ||
|
728598b230 | ||
|
e40368ae2b | ||
|
4ff17cb5a5 | ||
|
b7e6dd0dd4 | ||
|
8ee2091955 | ||
|
3fac550090 | ||
|
d29a1db134 | ||
|
653d97dda4 | ||
|
5364160d6a | ||
|
1a35948ff6 | ||
|
40c0f3756b | ||
|
3d6fd49179 | ||
|
d843e3d562 | ||
|
d8d5474dcc | ||
|
788e41a315 | ||
|
1bcc641dae | ||
|
f8fed0f308 | ||
|
d1e6632e6a | ||
|
710295bd2f | ||
|
3e2d68cd32 | ||
|
f3788525ff | ||
|
39d247a238 | ||
|
b37144b0b2 | ||
|
2e0b33f754 | ||
|
adc3f79c23 | ||
|
7904b454ba | ||
|
d264da8f08 | ||
|
6abe78ff46 | ||
|
9a4aa4288c | ||
|
50e3ccfa2b | ||
|
69a3c33ceb | ||
|
649b1ae868 | ||
|
973cc12ca9 | ||
|
436de45dd4 | ||
|
5f186a2835 | ||
|
ecec94ee7e | ||
|
196995a1a7 | ||
|
3a714fd4ac | ||
|
2132ec0269 | ||
|
c47fdc9aa0 | ||
|
5c4cfb54ae | ||
|
cd153a1fb3 | ||
|
b0ab92c921 | ||
|
5007a69eee | ||
|
8a46e050e3 | ||
|
256fd12da5 | ||
|
8e36ad09b4 | ||
|
96a92503cb | ||
|
5253153dbb | ||
|
12c78e622b | ||
|
216bf2e867 | ||
|
a086686e9f | ||
|
6402004018 | ||
|
955f833120 | ||
|
f4476f25bd | ||
|
8960d5bcfa | ||
|
605738757d | ||
|
569613f2a4 | ||
|
cc182ea2f3 | ||
|
3f96b2da7a | ||
|
9e44f94176 | ||
|
f94a7c6d82 | ||
|
dbf40bbbb8 | ||
|
954aae931e | ||
|
0b1200bb49 | ||
|
646d473e8e | ||
|
6975cd1622 | ||
|
b7f9bf43c2 | ||
|
388b627f72 | ||
|
f9019ab116 | ||
|
07657aecf4 | ||
|
e65904eee3 | ||
|
89847d5684 | ||
|
dada98143c | ||
|
713efff78e | ||
|
585303ad66 | ||
|
a800ed094b | ||
|
84e47f4aaa | ||
|
46ff9ce765 | ||
|
e31eb199c5 | ||
|
fd46442188 | ||
|
9837b7926f | ||
|
5aeaa248d4 | ||
|
739f6c78ad | ||
|
b75b6b513b | ||
|
2a3b48edaf | ||
|
7c7b33a0f8 | ||
|
40d72d1865 | ||
|
cdc2e7d4fe | ||
|
2628663590 | ||
|
5cc77eb6fd | ||
|
a1aa9d79c0 | ||
|
8b21034b31 | ||
|
67ffd8e923 | ||
|
af7edf4dff | ||
|
0fd3b9f7af | ||
|
7ef9f4dfdd | ||
|
6ce507f39f | ||
|
34cab91e86 | ||
|
63de9bdba3 | ||
|
afb6e7dfc3 | ||
|
ad89d1c876 | ||
|
6b80ac6500 | ||
|
2257dc9baa | ||
|
a40d9f3c72 | ||
|
977e7ae105 | ||
|
bc0fc5df98 | ||
|
810c10a0e9 | ||
|
bb469005b2 | ||
|
89ade65ad6 | ||
|
128d3ef94c | ||
|
b7e06085c7 | ||
|
8875e25fe9 | ||
|
44f9739750 | ||
|
9e85a023c1 | ||
|
b6698e686a | ||
|
66bd570584 | ||
|
e2c5a3895b | ||
|
fe719c1bc1 | ||
|
89fe6505f9 | ||
|
4b5f780ff0 | ||
|
31659efe13 | ||
|
2bd3776ddb | ||
|
c874f16c02 | ||
|
ba91304636 | ||
|
42a0f46268 | ||
|
d84ff06f73 | ||
|
87f33a4644 | ||
|
2d69b05c77 | ||
|
2eb57ee5cd | ||
|
85c69c2a4a | ||
|
c20f38b89c | ||
|
bfe196236f | ||
|
d4c61d2628 | ||
|
deef47c923 | ||
|
c19d8994b9 | ||
|
2de6da25a8 | ||
|
f13e76d022 | ||
|
95e2bde15b | ||
|
5c0a41a6e0 | ||
|
6424928ba3 | ||
|
4c280e59d4 | ||
|
56b7400dac | ||
|
d095a1bb96 | ||
|
76a89039ad | ||
|
ba2107ea8c | ||
|
f90e509bf6 | ||
|
dd8902bfcd | ||
|
3f44a33738 | ||
|
911af3f331 | ||
|
e2f083f885 | ||
|
e5a450349b | ||
|
7a20d69809 | ||
|
c187ae22e5 | ||
|
cb202a76df | ||
|
e1d139db2e | ||
|
51e695066a | ||
|
ce25fa4302 | ||
|
c403b61383 | ||
|
3ef7c25a16 | ||
|
442d211ee3 | ||
|
c0aad0a6d5 | ||
|
5903aea86f | ||
|
f4a68eae01 | ||
|
4a36b091f4 | ||
|
874ec8fc73 | ||
|
41ca67bf54 | ||
|
d72232f15b | ||
|
03c61685fb | ||
|
46284198f8 | ||
|
9916100835 | ||
|
bbb1da1a83 | ||
|
cf183288dd | ||
|
07075add3d | ||
|
338238d086 | ||
|
c6c74616d8 | ||
|
03bb729fea | ||
|
60460c025c | ||
|
f8a59446e8 | ||
|
a37c642127 | ||
|
4e61fb9cd3 | ||
|
b472c2df98 | ||
|
17f9242b58 | ||
|
bc67deee78 | ||
|
f57abae01e | ||
|
275b1d6897 | ||
|
e9a676951b | ||
|
b31d905704 | ||
|
c70c44b07b | ||
|
20583e3d15 | ||
|
9f4588cd0c | ||
|
b25e0f82b1 | ||
|
cae1c683aa | ||
|
57e7a5a34a | ||
|
230f1e1208 | ||
|
7bce70339f | ||
|
e1aaef7d4d | ||
|
1a1d154e14 | ||
|
384e5dd4c4 | ||
|
abfb147292 | ||
|
44eb03f78a | ||
|
857784747b | ||
|
7a2cb5e41c | ||
|
e662ed4adc | ||
|
712bdfc82f | ||
|
34bd47de79 | ||
|
fe57c13b51 | ||
|
f9df692056 | ||
|
f193b12059 | ||
|
2cd254954c | ||
|
4dab92ce69 | ||
|
d53f45d4e2 | ||
|
ca08614641 | ||
|
47adf4bce6 | ||
|
e69979d5a2 | ||
|
2ae68df41b | ||
|
7928cd20fb | ||
|
ad9049a49e | ||
|
dfcd60a9e2 | ||
|
0684df804d | ||
|
f8d6b84cb6 | ||
|
a980731bed | ||
|
b4e264251f | ||
|
8006a6cd82 | ||
|
a69db4169b | ||
|
5cd6b0c753 | ||
|
36ead3a720 | ||
|
bb339265fc | ||
|
bb4446e94c | ||
|
d2102671cd | ||
|
138e0c2301 | ||
|
37cfd289d8 | ||
|
9f3081580a | ||
|
2b6781bc65 | ||
|
a3248379db | ||
|
0774c8385c | ||
|
b2d30d68e7 | ||
|
82d10b882c | ||
|
24ae85fa56 | ||
|
1869aa3985 | ||
|
95b8ac5f62 | ||
|
0b4168cad4 | ||
|
3289472e31 | ||
|
4ad53339f6 | ||
|
a4d3da6a8e | ||
|
7954ea2525 | ||
|
bd1f0bcfd7 | ||
|
bc2e26d7ef | ||
|
fd80013917 | ||
|
f7d52564aa | ||
|
f7e8d1149a | ||
|
bd091caaf9 | ||
|
b455a1bf76 | ||
|
c0a3bcf9b3 | ||
|
5eedb5562f | ||
|
dc6c703741 | ||
|
16629d0b8e | ||
|
7f79210ed1 | ||
|
27a1a697e7 | ||
|
c1267004ef | ||
|
9cdd2214f9 | ||
|
fc29764911 | ||
|
989e9174c2 | ||
|
3993e12335 | ||
|
ac4d782937 | ||
|
32d18ca992 | ||
|
2df4b6c5d2 | ||
|
088d36da09 | ||
|
6f36faa4f9 | ||
|
3846384d56 | ||
|
331f141f63 | ||
|
62dd3d2a9d | ||
|
fa8a128e49 | ||
|
b10c308a5a | ||
|
e22c70e431 | ||
|
f4fe9e3421 | ||
|
da173615e4 | ||
|
dc6a17e092 | ||
|
f4180503c8 | ||
|
240d4193ae | ||
|
ac66e98ae9 | ||
|
d2935ffed0 | ||
|
c6e0fcea31 | ||
|
5d014d986b | ||
|
714994cad8 | ||
|
08fe61e058 | ||
|
0c8bed21ee | ||
|
98eb845f8c | ||
|
98300e3165 | ||
|
e22759d8f0 | ||
|
bf1411060e | ||
|
a4d142368b | ||
|
eb80f9b606 | ||
|
ae47b617e3 | ||
|
c116b8022e | ||
|
5b98e15613 | ||
|
e5b4011aa4 | ||
|
3125f93b3f | ||
|
f19c8e8c1d | ||
|
20779df686 | ||
|
752fba1691 | ||
|
637604d08f | ||
|
ba7b1d74d0 | ||
|
1a9989ade9 | ||
|
11844c987c | ||
|
8c45c88d15 | ||
|
c87bb2f239 | ||
|
32eeb9a0e0 | ||
|
df21fc8643 | ||
|
ffbdf31ac4 | ||
|
ccd9cc3dce | ||
|
81867402f6 | ||
|
4f5d61212b | ||
|
ef96123482 | ||
|
ee27ab0052 | ||
|
57f87ba083 | ||
|
a9bb72c6fd | ||
|
9506c2e597 | ||
|
32884357ff | ||
|
278ac08087 | ||
|
88204642b7 | ||
|
1401286910 | ||
|
12eb242224 | ||
|
8f36a02998 | ||
|
88f9e25f76 | ||
|
dba1c13954 | ||
|
df9faa1743 | ||
|
74fd975b57 | ||
|
ce85bcaee7 | ||
|
6eb6e806e7 | ||
|
6ed2a60978 | ||
|
fd04c14260 | ||
|
10a5273f07 | ||
|
bac3bf1a5f | ||
|
e3b684df21 | ||
|
e45b30d033 | ||
|
ad6fecefa8 | ||
|
3fdb2ccf55 | ||
|
29f5b55d42 | ||
|
5aef52e8c0 | ||
|
336e0cbf70 | ||
|
3cd06b0eb4 | ||
|
6bb46e3ecb | ||
|
127bc01857 | ||
|
a6975c1850 | ||
|
b2cb0725ac | ||
|
b974b144a8 | ||
|
bfb25fa47b | ||
|
3bb505d43f | ||
|
b135bcb9d9 | ||
|
4e97225424 | ||
|
0771cd8599 | ||
|
91d848f98a | ||
|
40edf8c6f5 | ||
|
e78562830f | ||
|
bef259a6eb | ||
|
39ce1bd8be | ||
|
6291881943 | ||
|
802fd94dad | ||
|
66f38a1b31 | ||
|
d3850a4da5 | ||
|
53a4355e60 | ||
|
18a616f57c | ||
|
32333eb627 | ||
|
19def41fdf | ||
|
44b9dce134 | ||
|
fa5a538fe5 | ||
|
5e3fd2253f | ||
|
9643c2c1e3 | ||
|
93f3614382 | ||
|
cbc8a7d679 | ||
|
290bc993a5 | ||
|
3694657eb6 | ||
|
79417e07ca | ||
|
dad95c873b | ||
|
626b35e1b0 | ||
|
5881ba43f8 | ||
|
fed7b97dcb | ||
|
c4458c9d9a | ||
|
7bae2a4547 | ||
|
aeb3e647d4 | ||
|
fe036cbe77 | ||
|
952ec65a40 | ||
|
b8788421d5 | ||
|
c2347db934 | ||
|
27ead5d4fa | ||
|
591ae700ce | ||
|
6ade7c0a8d | ||
|
8766b36144 | ||
|
b3745f2614 | ||
|
ca8a9c600a | ||
|
a0225507a0 | ||
|
d39a88d63f | ||
|
e5d353d0a7 | ||
|
de422c822d | ||
|
4d3326b542 | ||
|
1b82138142 | ||
|
208ff8e350 | ||
|
ec54b36e05 | ||
|
38e8522cbf | ||
|
52f8687397 | ||
|
43600ffcf8 | ||
|
938d2d9e6e | ||
|
9368dbe0e7 | ||
|
fe3290601a | ||
|
e7173e1d62 | ||
|
2ffcfdcd25 | ||
|
8aafe64397 | ||
|
2140303fcc | ||
|
b80ded63ca | ||
|
7be2521a31 | ||
|
15b9d54a32 | ||
|
bc1a4e12ad | ||
|
67419e8d0a | ||
|
849aaf7435 | ||
|
a89ee8c406 | ||
|
0c6f172e75 | ||
|
a67349b076 | ||
|
f9b68a5d17 | ||
|
c7910b51a1 | ||
|
1f99710b21 | ||
|
5e558c361b | ||
|
5f39efcdfd | ||
|
037edf1215 | ||
|
37125866ca | ||
|
421e73b87c | ||
|
0d8de289dd | ||
|
00916dec38 | ||
|
c115e5677e | ||
|
56047c1c83 | ||
|
09d85631dc | ||
|
f25e4dc3ed | ||
|
a3a7c2d24e | ||
|
0126168472 | ||
|
e9f795c5ce | ||
|
8d460a7300 | ||
|
0c7e1889e4 | ||
|
8b2bec700a | ||
|
125267544e | ||
|
0d55ed3600 | ||
|
ad0cd6939a | ||
|
a1244d7bd3 | ||
|
33adb334cd | ||
|
ef87a8a1f0 | ||
|
5223a80ab8 | ||
|
a595c84f7e | ||
|
adcfcc1178 | ||
|
b158dbcf79 | ||
|
ab3832f3e7 | ||
|
9bf415f749 | ||
|
a2bda9e5f1 | ||
|
0195725563 | ||
|
ec1170bd37 | ||
|
66c67dbe73 | ||
|
e5d8d8234d | ||
|
16ae2c1809 | ||
|
5c5e879c2c | ||
|
4771716ab2 | ||
|
b156585739 | ||
|
7a77b5c419 | ||
|
9872b594bf | ||
|
e6c88db0a0 | ||
|
257280a050 | ||
|
520103df78 | ||
|
3e3787de15 | ||
|
0c824d5ef1 | ||
|
c0e989b17c | ||
|
5218b3af82 | ||
|
ef0a91da27 | ||
|
8412181746 | ||
|
400ee2aa57 | ||
|
05b8466f87 | ||
|
6061c691e6 | ||
|
3ac967a7b6 | ||
|
19962f6b6a | ||
|
f7703dbca3 | ||
|
74a9eedb93 | ||
|
6df104b275 | ||
|
b27453d8d8 | ||
|
4470ee4ccf | ||
|
df27fd1e9c | ||
|
97c68810e0 | ||
|
8a86acf75d | ||
|
160e479f8d | ||
|
d738acf638 | ||
|
84d92aa3c7 | ||
|
dd01cabcdc | ||
|
e196adb98c | ||
|
c383c7e2c1 | ||
|
958bb5285d | ||
|
f0317ae70b | ||
|
591941bd39 | ||
|
e90769c869 | ||
|
256bbb1a8a | ||
|
2c7c956be9 | ||
|
fe81bba08d | ||
|
564de07963 | ||
|
84cf6fbe83 | ||
|
d9160f19c0 | ||
|
ba0a03a8ba | ||
|
b0f04d925a | ||
|
7b78e68727 | ||
|
ec53b8b66a | ||
|
6e949bf951 | ||
|
86fb669fd3 | ||
|
7123956ecd | ||
|
46cf6b77cf | ||
|
a52bc44f5a | ||
|
acb63a57fa | ||
|
5b08277ce4 | ||
|
5dc56df64e | ||
|
33c4d64b62 | ||
|
25de6825df | ||
|
0b60201a1e | ||
|
cfea99c4ee | ||
|
cea41a544e | ||
|
8371a060a0 | ||
|
7ed140cea7 | ||
|
cb97c2184e | ||
|
0b4fcc83bd | ||
|
514359e556 | ||
|
55b9d02a99 | ||
|
fc9a65be2b | ||
|
49dff97d9c | ||
|
4efb0b78fa | ||
|
c9fe8fde59 | ||
|
74d54946bf | ||
|
16462292e1 | ||
|
7ef1e1ef9d | ||
|
20d80311f0 | ||
|
f1a1f53f72 | ||
|
3acc42c5b3 | ||
|
c766bd077b | ||
|
54320c5b09 | ||
|
291b71ea3b | ||
|
356515222a | ||
|
688e589e0c | ||
|
6c98201aa4 | ||
|
d4b10eb9f5 | ||
|
728d56e74d | ||
|
a9f4038fcd | ||
|
77f1d4b0f1 | ||
|
d78577c810 | ||
|
5fb6b2eaf7 | ||
|
404caa111a | ||
|
b838468500 | ||
|
f2235be1d3 | ||
|
6ec45b10f1 | ||
|
d9879d8026 | ||
|
d487b2f927 | ||
|
66e5e14bac | ||
|
7e4668859b | ||
|
92d038062e | ||
|
2972bceb90 | ||
|
cb0a60a0fe | ||
|
3ee91e15ff | ||
|
ef47a73382 | ||
|
dc515e5ac5 | ||
|
56763d4288 | ||
|
ad9fa73301 | ||
|
10dd049912 | ||
|
4209f1cbfd | ||
|
ee83e874a8 | ||
|
27ed73e3e3 | ||
|
e41c0532e3 | ||
|
eeb7274d65 | ||
|
eb0dcf6063 | ||
|
83be0735cd | ||
|
fe4ba51d1a | ||
|
adf575b75e | ||
|
e5426f74a8 | ||
|
f5212d3b79 | ||
|
3d09c4be75 | ||
|
f2db15873d | ||
|
7c663de6c9 | ||
|
c14bbcdbf2 | ||
|
1be4c1935a | ||
|
764b1aa5f8 | ||
|
d13b07ba59 | ||
|
028afab908 | ||
|
55dfae2a52 | ||
|
994324e19c | ||
|
b81c0d869c | ||
|
f14f04c5ea | ||
|
9c86da1403 | ||
|
cb611b5ed0 | ||
|
891269ef39 | ||
|
ab171a1d6d | ||
|
a56738324a | ||
|
da61b8e7c9 | ||
|
d6d58bc938 | ||
|
e42cb43ca5 | ||
|
ca541c7e4a | ||
|
96e14424f0 | ||
|
47830896e8 | ||
|
5fd4b4afae | ||
|
dae9f6d3c2 | ||
|
8e1210f96e | ||
|
56aa683f28 | ||
|
1b9a6d7ad8 | ||
|
f591c4db56 | ||
|
371fa51e82 | ||
|
a927ed2da4 | ||
|
a55675acf8 | ||
|
25dd3d476a | ||
|
3ff5f40bdb | ||
|
689ded0413 | ||
|
327ed157ef | ||
|
c819238da9 | ||
|
477afa8711 | ||
|
bd272e0b3c | ||
|
1067595b5c | ||
|
14c232e3c4 | ||
|
57f5fb1f4f | ||
|
bcddfb786d | ||
|
20db1738fa | ||
|
b23d81f825 | ||
|
bc15ceaba1 | ||
|
6f17d0817b | ||
|
a1cde03b20 | ||
|
cfce23950a | ||
|
64740249ab | ||
|
126f42de06 | ||
|
d94e3a81eb | ||
|
70d0235770 | ||
|
30b5493fd6 | ||
|
4f6362515f | ||
|
dbbe9419e5 | ||
|
188bae142b | ||
|
7c2b12ebd7 | ||
|
ef8e35e39b | ||
|
975accbe1d | ||
|
aaa27d0a34 | ||
|
9302ce0036 | ||
|
0aab3c97a0 | ||
|
8e731337ba | ||
|
b294db5aed | ||
|
8d766a2ca9 | ||
|
f2ae16e71d | ||
|
ac281476c8 | ||
|
1b1c8d31a9 | ||
|
4b587aaf99 | ||
|
016301508e | ||
|
6744726089 | ||
|
0a89f88b89 | ||
|
69fac8ea58 | ||
|
a51104e844 | ||
|
943aaf84e5 | ||
|
e8bde03a50 | ||
|
75b13caf0b | ||
|
0f231f0e76 | ||
|
5d99fa0940 | ||
|
649388188b | ||
|
9fa1873a65 | ||
|
f2057dd43d | ||
|
eeffbbb43c | ||
|
aaa0105f75 | ||
|
f29a42721f | ||
|
079d317ade | ||
|
6f1fd12265 | ||
|
e16b57aa05 | ||
|
fb30f65951 | ||
|
a47aaae078 | ||
|
7117614ee5 | ||
|
e26aec96b0 | ||
|
c60d104056 | ||
|
e6ff8c92a0 | ||
|
9bce364b3c | ||
|
cbaa2b5773 | ||
|
0453ed8235 | ||
|
a341adb7f3 | ||
|
4c88ac69f2 | ||
|
85c237bc1d | ||
|
35d48cc88c | ||
|
957b7115fe | ||
|
82eedbd622 | ||
|
b930b0ef5a | ||
|
ad313c9d49 | ||
|
06035c0f4e | ||
|
e1384f6618 | ||
|
3acb86805b | ||
|
bf0af1cd3d | ||
|
c77d11f1c7 | ||
|
d279d145d5 | ||
|
fc7905653e | ||
|
660282e82f | ||
|
77602dbb93 | ||
|
a3e6896a43 | ||
|
702ce446df | ||
|
8ae77e955e | ||
|
783924e671 | ||
|
93304e5f58 | ||
|
917373ee55 | ||
|
7a98ad50b4 | ||
|
982058cc19 | ||
|
576beaa6a6 | ||
|
6eb22c5db2 | ||
|
72a0d78b3c | ||
|
13d08af054 | ||
|
80a7ae9845 | ||
|
6c30a7b2eb | ||
|
76b72338da | ||
|
a39e78d42d | ||
|
4550dccb84 | ||
|
01ce09f343 | ||
|
71dca67ca2 | ||
|
327f9baccf | ||
|
a98b866a66 | ||
|
3aabba7535 | ||
|
c22cfa255b | ||
|
af211b3d71 | ||
|
6bb3463e7c | ||
|
8b151d12b9 | ||
|
ecb6dc3679 | ||
|
49a223a17d | ||
|
e5cfdc648c | ||
|
9f9f70aade | ||
|
e91c04f586 | ||
|
277fa6c12d | ||
|
ca3050ec3d | ||
|
1b3ced152b | ||
|
97031f9133 | ||
|
c92506e2e7 | ||
|
65a9772adf | ||
|
1e07ee6cc4 | ||
|
01a130273f | ||
|
3c710219a1 | ||
|
2ba285a544 | ||
|
72ae7638bc | ||
|
3bfad5ca73 | ||
|
668d02846d | ||
|
781f31d2b8 | ||
|
df28db0066 | ||
|
20183f3860 | ||
|
48edf1757b | ||
|
2645e88b0c | ||
|
db121049b3 | ||
|
8058cdbc0e | ||
|
31d357284a | ||
|
4ee77ce026 | ||
|
8373129588 | ||
|
9a3c6f236d | ||
|
55ba81fee5 | ||
|
bc5159a1f5 | ||
|
af007c7189 | ||
|
dc79d07303 | ||
|
79167c7577 | ||
|
08dd057864 | ||
|
fee3f288c0 | ||
|
b22bef5cfb | ||
|
7ad5523113 | ||
|
460b5824c3 | ||
|
b0a28b1e80 | ||
|
ca6535f210 | ||
|
1155008719 | ||
|
d07594ed59 | ||
|
5efda3eda9 | ||
|
4b137efdbd | ||
|
383d582b47 | ||
|
6eacedc443 | ||
|
b1a5bb593c | ||
|
9369c6549a | ||
|
c7731a3b93 | ||
|
24706c163a | ||
|
a276dc47e0 | ||
|
e55f8a61cd | ||
|
c8bcca0845 | ||
|
cb6892d2ed | ||
|
43eda8d878 | ||
|
a2534e03bd | ||
|
dc5b955930 | ||
|
5de7896ffb | ||
|
01af45d14a | ||
|
cc9f3ea938 | ||
|
ff43de695e | ||
|
8bc717a55c | ||
|
d09222c900 | ||
|
87cdb81fae | ||
|
38eb1d548a | ||
|
e0960f6288 | ||
|
74403f2003 | ||
|
b2c83714d1 | ||
|
2c21672de6 | ||
|
f7dc21773d | ||
|
3e457e4edf | ||
|
03572d175f | ||
|
c4894d6092 | ||
|
3fb0383df4 | ||
|
ee36763f9d | ||
|
955c5549ae | ||
|
4a34514b21 | ||
|
805d9f22ce | ||
|
20f29327e9 | ||
|
018b5039e7 | ||
|
d6aeb767a0 | ||
|
b5d3d4741f | ||
|
85c747d444 | ||
|
927e6d89d7 | ||
|
3d87f23bf5 | ||
|
45845d4a2a | ||
|
00ef129b2a | ||
|
06b219217b | ||
|
789910d8eb | ||
|
a8e6a0763d | ||
|
e1386ba604 | ||
|
83deecb9e9 | ||
|
d8dcb8f6e0 | ||
|
5fa31eaead | ||
|
d245201614 | ||
|
a5b84a47b0 | ||
|
552b2f0635 | ||
|
0b3badf3d8 | ||
|
cea3e224aa | ||
|
1eaf0e1c63 | ||
|
2cda982345 | ||
|
c9734b6d7b | ||
|
fd01377f12 | ||
|
8d2fc88336 | ||
|
092bf07cbf | ||
|
5145a8e8be | ||
|
b495d36fa5 | ||
|
3bdeaa4a6f | ||
|
d1f58fed4c | ||
|
12e918bd31 | ||
|
637f445c3f | ||
|
d0e4cf5895 | ||
|
e0bf8b2aab | ||
|
483c06b4ab | ||
|
f4a3b31415 | ||
|
5c7e309d13 | ||
|
7a72b2d558 | ||
|
c75b21a510 | ||
|
a9f318d523 | ||
|
1dca0bd8d7 | ||
|
f3165a716a | ||
|
9f45eba6f6 | ||
|
ecaa7dad49 | ||
|
ee84e34570 | ||
|
442be2ac02 | ||
|
22d600e8c0 | ||
|
e160018826 | ||
|
d1a02bd3e9 | ||
|
380fb986b6 | ||
|
e7f794531e | ||
|
992023288f | ||
|
ef5a36dd69 | ||
|
3ab90db6ee | ||
|
e26be9cb8a | ||
|
bba555bb08 | ||
|
4b0af73dd2 | ||
|
da72b8c385 | ||
|
44079b7176 | ||
|
19c36fe4c9 | ||
|
a742d10c54 | ||
|
6bd27038cc | ||
|
5df757a403 | ||
|
38f5d1b18e | ||
|
5f75d4c099 | ||
|
319a0d65af | ||
|
3d2680a102 | ||
|
c36fb5919a | ||
|
46d3f4369e | ||
|
c2b3920b50 | ||
|
6e7323e3e8 | ||
|
e98b0371e5 | ||
|
f085419055 | ||
|
1fedbded62 | ||
|
c8258171ca | ||
|
007ee0da8e | ||
|
5e1ac9ce87 | ||
|
a7cd08603e | ||
|
854cd1a517 | ||
|
cf8c74cb07 | ||
|
23565ebe62 | ||
|
8467bce2a6 | ||
|
e6225d70a1 | ||
|
a69de8be40 | ||
|
649654207f | ||
|
3123502f4c | ||
|
17d54cffbb | ||
|
bddee7c38e | ||
|
6f9c311285 | ||
|
0cfa6a8981 | ||
|
d5516a4ca9 | ||
|
d2b793057e | ||
|
b2a409fd4d | ||
|
4ba237c5d8 | ||
|
f5ef02d4cc | ||
|
ec2255764a | ||
|
1a8e92c922 | ||
|
5c1891ec9f | ||
|
83265b7f75 | ||
|
5364a10033 | ||
|
c2a46e4aa3 | ||
|
bae5ce0bfa | ||
|
cc5edb720c | ||
|
e17c2ef698 | ||
|
61b74f9a5b | ||
|
0cd83eadc0 | ||
|
1757c45490 | ||
|
d85f98d2a9 | ||
|
9e123011c2 | ||
|
774c4d0d6f | ||
|
7332679678 | ||
|
bb6f727f25 | ||
|
586d2a41ce | ||
|
91dff61008 | ||
|
8203383c03 | ||
|
a3c88a0de5 | ||
|
fff0aec720 | ||
|
b73786c6d5 | ||
|
67eeccb31f | ||
|
266ca9318d | ||
|
3e97299a46 | ||
|
eacc42fedd | ||
|
db3e8edacd | ||
|
6e41634295 | ||
|
ef3c2d86d3 | ||
|
780308c194 | ||
|
696fd690ae | ||
|
d323501c7f | ||
|
66d8b2c18a | ||
|
6d8a415b4d | ||
|
dad268a686 | ||
|
e7acc2fddf | ||
|
6fb17a813c | ||
|
11ede9f872 | ||
|
6ac1c1c886 | ||
|
01c0ab4f06 | ||
|
7713f35326 | ||
|
7220b09ff9 | ||
|
b7298ef51a | ||
|
16b10b026b | ||
|
9b18c073b6 | ||
|
dd89e705f2 | ||
|
56b86bbfca | ||
|
7e2aafcc76 | ||
|
11c774b04f | ||
|
6ba926381b | ||
|
af55e179c7 | ||
|
18a42e4b38 | ||
|
a10ccadb54 | ||
|
15fee582cc | ||
|
43408634bb | ||
|
d47fce6ce7 | ||
|
9e64267867 | ||
|
7ae5785447 | ||
|
ef8d3f684f | ||
|
cc6e3d14ce | ||
|
83f44b1ac1 | ||
|
1f470eadd1 | ||
|
005b01bd9a | ||
|
6f67367b57 | ||
|
9ee0600a7f | ||
|
30cc7c847e | ||
|
a5bb24b886 | ||
|
f02d810af8 | ||
|
55f6b6a6ab | ||
|
b999ee60aa | ||
|
85afd3ef14 | ||
|
1907030d89 | ||
|
361a5eac7e | ||
|
fecb41d2ef | ||
|
71dabf9fb3 | ||
|
4cdb641e7b | ||
|
efa2dff681 | ||
|
31a7b7d24e | ||
|
af8cc4dc4a | ||
|
8eb60f5624 | ||
|
791ea89b88 | ||
|
c572760a66 | ||
|
69fc19f7e0 | ||
|
b939c24b3d | ||
|
3eb494dbe3 | ||
|
d6a66c83c2 | ||
|
582a9a5db8 | ||
|
0afbc19ffb | ||
|
ac9290f985 | ||
|
a133ba1998 | ||
|
5657738f7e | ||
|
d310acc1eb | ||
|
2b88f10b04 | ||
|
883ba7aa90 | ||
|
28f55deaae | ||
|
40407930d5 | ||
|
674b71b535 | ||
|
677d9c47ac | ||
|
2638ab98ad | ||
|
bc3068c2f9 | ||
|
2bde9bea1c | ||
|
502f2f040d | ||
|
041d4d666e | ||
|
c0c10a97e7 | ||
|
5a7c50027f | ||
|
88b5065e7d | ||
|
b690008192 | ||
|
2d6bc9536c | ||
|
01dc6b2f0e | ||
|
d8aa2d0a9e | ||
|
19bb97d24d | ||
|
9f4f168804 | ||
|
82e133b382 | ||
|
cf3083d68e | ||
|
e796cdbb27 | ||
|
2d44582f88 | ||
|
2a61344c03 | ||
|
77c6aad1b5 | ||
|
b60a897265 | ||
|
fdd41c706a | ||
|
d68cfeed6e | ||
|
14911e0d22 | ||
|
9503434d53 | ||
|
c3c9e955e5 | ||
|
72d5db92a8 | ||
|
3f302c8d47 | ||
|
04a769bb37 | ||
|
f9d4a1c1d8 | ||
|
3e7db46195 | ||
|
e52aca4837 | ||
|
5ec503bd6f | ||
|
49be805001 | ||
|
94596388f7 | ||
|
5c4980c6e0 | ||
|
6d157f0b3e | ||
|
c3d5fdff64 | ||
|
d6cbdbd6aa | ||
|
d7b8fb3113 | ||
|
45044c2d75 | ||
|
a9f260d135 | ||
|
072b3b9d8c | ||
|
ae7f59e249 | ||
|
450b4e16b2 | ||
|
c48ffa24be | ||
|
7f0c0a0922 | ||
|
bce1c62308 | ||
|
9b3aa3451e | ||
|
436c0b58db | ||
|
7ac62822cb | ||
|
af8ae83ea0 | ||
|
0bcecae2a3 | ||
|
bd130315b6 | ||
|
504711647e | ||
|
a9a016d7b1 | ||
|
ab12b23e6f | ||
|
797bdbd998 | ||
|
1c45d37348 | ||
|
b521255ec9 | ||
|
75ea001bfe | ||
|
ff2fb9196f | ||
|
acae0fe4a3 | ||
|
ccc11e5680 | ||
|
2670eefcd4 | ||
|
c0cae9e8a0 | ||
|
f8cf6b4f7c | ||
|
a29182a010 | ||
|
1cfe0beac0 | ||
|
798f90c4d5 | ||
|
fac4334950 | ||
|
f8d44a8a88 | ||
|
1136a94a6e | ||
|
fd20e0de90 | ||
|
a1150dc334 | ||
|
b4d06ff8dd | ||
|
7581705007 | ||
|
5a5707159a | ||
|
742a1681ce | ||
|
fba9b9cb65 | ||
|
61b2d7548a | ||
|
80828a7c77 | ||
|
f5af86c9d5 | ||
|
58acbe7caf | ||
|
355b92d7ba | ||
|
d42e4f2344 | ||
|
fbded9cdac | ||
|
907e43b9d5 | ||
|
fb467df47c | ||
|
48beef25fa | ||
|
a3f568fc64 | ||
|
57ee304260 | ||
|
0794a866a7 | ||
|
49e4d344da | ||
|
21a9dea99f | ||
|
6e505c0c3f | ||
|
e9a294fd9c | ||
|
44d851d5bb | ||
|
5ed03ce7f0 | ||
|
c1b9660ec8 | ||
|
c2c334d22f | ||
|
ed5c848473 | ||
|
f144fd1ed3 | ||
|
e96557f410 | ||
|
ac96d5ccf0 | ||
|
b2af19471e | ||
|
6805d0ff2b | ||
|
6e1de9d820 | ||
|
d27ca7854f | ||
|
c4e57477fb | ||
|
f1c59a91a1 | ||
|
74c573ef04 | ||
|
5f082bc0e5 | ||
|
0e3b7127b5 | ||
|
5d3414a40b | ||
|
f4638c7580 | ||
|
8b0b500c89 | ||
|
04746fc4d8 | ||
|
463ef3f8bc | ||
|
5e2f78424f | ||
|
3889c2e01c | ||
|
1887e984a0 | ||
|
a495bbc1db | ||
|
cd429d3654 | ||
|
771aef0b44 | ||
|
f7ef452d8a | ||
|
0f64f8db90 | ||
|
c04a6254b9 | ||
|
485e17d6ed | ||
|
952ab03d2a | ||
|
bbb524018e | ||
|
859c08620b | ||
|
f6cd42e6e0 | ||
|
61ee67d612 | ||
|
939c1def5d | ||
|
b7ab80e8ea | ||
|
b69d4b0ecc | ||
|
2f437d7452 | ||
|
d761216ec1 | ||
|
088e9be931 | ||
|
32ecac6464 | ||
|
7760c3e4aa | ||
|
3cfb76e57f | ||
|
e1faeb0f6c | ||
|
25bff851dd | ||
|
3a39904011 | ||
|
7e1fbfba64 | ||
|
a52064184e | ||
|
b4a1ba828a | ||
|
c8c6105ee2 | ||
|
0b49eeeba3 | ||
|
b0830f0cd7 | ||
|
565d4a53b0 | ||
|
9624662bf6 | ||
|
8195957461 | ||
|
02fed4a082 | ||
|
34ecf4ea51 | ||
|
a422ad0d50 | ||
|
096d96e344 | ||
|
e61310bc89 | ||
|
111ca9584e | ||
|
7d35c4592c | ||
|
3e8386cbf3 | ||
|
4354162067 | ||
|
a62a444229 | ||
|
f6b72fa830 | ||
|
9667e8615f | ||
|
026da060f2 | ||
|
3feab1cb2d | ||
|
804e9a09c0 | ||
|
4c6829513c | ||
|
4038954f96 | ||
|
52a6dd5427 | ||
|
c301dd5d94 | ||
|
28473e919f | ||
|
69636d2453 | ||
|
7cb7eee29d | ||
|
a52e1069ce | ||
|
a8e5002aeb | ||
|
c515a351c6 | ||
|
7777b30693 | ||
|
d04fbf3f78 | ||
|
54207877bd | ||
|
3c6b1480b8 | ||
|
b075960e3b | ||
|
85596c2610 | ||
|
0613e3c24d | ||
|
ee5f009b95 | ||
|
d76816d043 | ||
|
45274560ec | ||
|
02a8e78902 | ||
|
8f3d9e93ce | ||
|
a244aca6a4 | ||
|
5ae85b9de5 | ||
|
d176818c44 | ||
|
aeec0f9a71 | ||
|
08a02af833 | ||
|
cf26585cff | ||
|
3f4a375ac4 | ||
|
cc632f2713 | ||
|
5ebc9a380c | ||
|
6453650895 | ||
|
9cb12cf250 | ||
|
68e8d74545 | ||
|
fc054e21f6 | ||
|
3256f4bc0f | ||
|
0e9ad8f2c7 | ||
|
efbb5b2db3 | ||
|
85ed4157ff | ||
|
a43569c8a5 | ||
|
e771d0ea39 | ||
|
9073eba405 | ||
|
a5cd73d047 | ||
|
a0b1eda1d0 | ||
|
ad80e09ac5 | ||
|
77e5171679 | ||
|
0c66418dad | ||
|
45a9eac7d2 | ||
|
838adf7475 | ||
|
fa05d15093 | ||
|
1122740bd7 | ||
|
f877278075 | ||
|
cbaa6abdd0 | ||
|
76a4803292 | ||
|
b286b2eb31 | ||
|
295103adc0 | ||
|
d31c040dc0 | ||
|
8a63b35f44 | ||
|
bfff06d402 | ||
|
21d3d75827 | ||
|
2c3538981a | ||
|
30a9899262 | ||
|
dd10b8a27c | ||
|
dbf13290f5 | ||
|
f9ff93c606 | ||
|
df476b0088 | ||
|
56664b34a6 | ||
|
efb45733de | ||
|
0cbc3d8df6 | ||
|
27b4e61c9f | ||
|
069606947c | ||
|
6ae6b7cfcd | ||
|
d197ce230f | ||
|
c6cb0d3984 | ||
|
00cfead9bb | ||
|
20b1e4db0b | ||
|
a098a32f7d | ||
|
9ee9a1033f | ||
|
eb904668b2 | ||
|
75b69876a3 | ||
|
08d9d24320 | ||
|
c7d61af332 | ||
|
5f7607412b | ||
|
403fea39f7 | ||
|
f2a4619c57 | ||
|
712872efba | ||
|
8cbf3fe5f8 | ||
|
02137f8cee | ||
|
43ea281a7f | ||
|
0006e5ab45 | ||
|
d821448e2f | ||
|
3bd46f7ac8 | ||
|
ebf9daf73e | ||
|
2ba66f0b26 | ||
|
0afadb9149 | ||
|
19d0159e33 | ||
|
d4f15ab402 | ||
|
527e030283 | ||
|
634e6a381c | ||
|
042d094ce7 | ||
|
3cc1491833 | ||
|
d19e6dec7a | ||
|
6becfc52a8 | ||
|
a2cbbc5c4f | ||
|
10173525d8 | ||
|
ccdb72a422 | ||
|
df96617d3c | ||
|
09aa3e0e79 | ||
|
a673e97f02 | ||
|
43e86921e0 | ||
|
ad58e08a41 | ||
|
0bfc2d0f2f | ||
|
475a42767a | ||
|
ce4eefff6a | ||
|
82b247d1a4 | ||
|
a21eb036ee | ||
|
9c1701f2aa | ||
|
fd17c37feb | ||
|
cde5451e79 | ||
|
ca9ea097df | ||
|
b84cc14694 | ||
|
a84175b3b9 | ||
|
438b4e9625 | ||
|
a510e7b8f3 | ||
|
e16ebcad6e | ||
|
e91e58aec9 | ||
|
3629b9051d | ||
|
ef919d963b | ||
|
4545114408 | ||
|
9ed32b9dd0 | ||
|
45dbe6d542 | ||
|
bff955ff7e | ||
|
80c0e747a7 | ||
|
617edda9ba | ||
|
7ab04b2e73 | ||
|
e89056a614 | ||
|
97ebbb9672 | ||
|
c02213e4af | ||
|
73e0aeb4ca | ||
|
a1ec6f401c | ||
|
5337d37a1c | ||
|
d92d955aeb | ||
|
7ac84d386c | ||
|
8397baa700 | ||
|
2d65554cb9 | ||
|
64e40d471c | ||
|
c5ea29649b | ||
|
410438a0e3 | ||
|
fbaef7e60f | ||
|
017a813621 | ||
|
4c891b8bb0 | ||
|
948d9bdadb | ||
|
b7258ec3bb | ||
|
93cb5a5bd6 | ||
|
d8f46c4410 | ||
|
d0757ccc5e | ||
|
f4f730bd8a | ||
|
f5e27f1a21 | ||
|
bb6415ddc4 | ||
|
2b6179841b | ||
|
e877cd2874 | ||
|
203ddfcd43 | ||
|
09847567ae | ||
|
732ae69d22 | ||
|
2b10376339 | ||
|
9667ac3baf | ||
|
b5be335db3 | ||
|
d33945780d | ||
|
5f4cc3e1de | ||
|
ec567bd53c | ||
|
aeadaa1184 | ||
|
2f0f0006e3 | ||
|
de047a2b8c | ||
|
86a35652bb | ||
|
6ae70e03cb | ||
|
2c532cb74d | ||
|
779f20d64e | ||
|
89ae9f1f88 | ||
|
ed1ab11001 | ||
|
d2e010cbe1 | ||
|
a44a0990f5 | ||
|
2f88c9eefe | ||
|
60f1936a62 | ||
|
ee15f99dd7 | ||
|
b0ee27ba46 | ||
|
067bbaa473 | ||
|
c07d60bc90 | ||
|
29fd957352 | ||
|
ef10ce04e2 | ||
|
f0269b28f4 | ||
|
0a7c6eb9dc | ||
|
3f0c13af8a | ||
|
fcd78eb1f7 | ||
|
17dfae6d4e | ||
|
e414c25fd7 | ||
|
34a71554ae | ||
|
3b1a196c75 | ||
|
105dbf471e | ||
|
d4d9f27a8d | ||
|
68df0d4909 | ||
|
9c572fe54b | ||
|
245e05ce61 | ||
|
f4ec2d18e5 | ||
|
4124d84c00 | ||
|
3c713a3f53 | ||
|
89e570493a | ||
|
16674774c7 | ||
|
0180ad7f38 | ||
|
bfd1ea1da1 | ||
|
3eacd0c871 | ||
|
d587270293 | ||
|
3eb13e83cf | ||
|
df761713aa | ||
|
de50f37fea | ||
|
bad6076905 | ||
|
c2bd76a22e | ||
|
010fe30b53 | ||
|
e5779ab786 | ||
|
71e14a13b4 | ||
|
491074aab1 | ||
|
54af533b31 | ||
|
4f13043d14 | ||
|
6a5df4d999 | ||
|
d41602088b | ||
|
f3a0f73588 | ||
|
be1e1b41bd | ||
|
fd30131dc2 | ||
|
5122697f0b | ||
|
b7bf502e02 | ||
|
3f70e3a843 | ||
|
cae2982d81 | ||
|
b638c89556 | ||
|
9bc51bd0e2 | ||
|
408b4f3f42 | ||
|
d818ac1d59 | ||
|
bd1c764a1a | ||
|
8f377ad8bd | ||
|
df3e11bdb8 | ||
|
97dabbe997 | ||
|
5a7a3f6d4a | ||
|
b4327fdc99 | ||
|
10f924a617 | ||
|
3dd6a01c8b | ||
|
585afef945 | ||
|
bdc65990e1 | ||
|
f2e4ffcac2 | ||
|
ae66b6e648 | ||
|
923057c1a8 | ||
|
0f6e08d34f | ||
|
4889a3e2e1 | ||
|
39d87a96aa | ||
|
e7c03ba66a | ||
|
08822ec684 | ||
|
6463a01e04 | ||
|
0cf1850465 | ||
|
1418fb394b | ||
|
e4eda88ca9 | ||
|
71a3c97d6f | ||
|
1c3d2924ae | ||
|
a11b9d28bd | ||
|
b54eb609bf | ||
|
dc8ff413f9 | ||
|
f8ffa1601d | ||
|
da01bc1fbb | ||
|
a2079a9ca9 | ||
|
bbc8c09753 | ||
|
a627299468 | ||
|
e5fdc63bdd | ||
|
fe83e70074 | ||
|
46c177b982 | ||
|
1df50adc1c | ||
|
b6cd9a4c4b | ||
|
2333ec4d1f | ||
|
85a8a54d3e | ||
|
7294a22901 | ||
|
f4b7474ade | ||
|
9428321607 | ||
|
882544446a | ||
|
73160c9b90 | ||
|
2184d6a3ff | ||
|
6e35895b44 | ||
|
8009ff8537 | ||
|
9bf792ce0b | ||
|
f05aaeb329 | ||
|
1bdf34e7dc | ||
|
cd25bfca91 | ||
|
1b621ab81c | ||
|
cb2e5ac776 | ||
|
8ce32eb3e1 | ||
|
aae0314bda | ||
|
35d5248d41 | ||
|
0ccc2555d3 | ||
|
b26a711e96 | ||
|
2218a052b2 | ||
|
40f419ca54 | ||
|
f742fc3dd1 | ||
|
33fbcc56d6 | ||
|
61d05dea58 | ||
|
8a821060a3 | ||
|
0d44599a63 | ||
|
8e29b08070 | ||
|
b6c3e61603 | ||
|
dc08b75c6a | ||
|
5420fa942e | ||
|
1ee33d3a8d | ||
|
61dab8dc0b | ||
|
0022a2b29e | ||
|
b2a27ed089 | ||
|
d8ae50800a | ||
|
43fa72b7b7 | ||
|
36b62b7270 | ||
|
73204c868d | ||
|
2ee889843a | ||
|
74b78e75a1 | ||
|
6905edbeb6 | ||
|
6c69da1573 | ||
|
e776dfd800 | ||
|
95bf380d07 | ||
|
2a61ad1b57 | ||
|
80703010bd | ||
|
e88c10670e | ||
|
2a2953c674 | ||
|
1054f37765 | ||
|
f77257cf79 | ||
|
f004cc07df | ||
|
065a4da72d | ||
|
98c7f2eb13 | ||
|
d332502d3d | ||
|
a7bf7867d7 | ||
|
c63cda7c21 | ||
|
caab0cdf27 | ||
|
1191876ae8 | ||
|
fa51a589ef | ||
|
3f274115b0 | ||
|
3b0918981e | ||
|
a327dfeed7 | ||
|
d8cef34d6c | ||
|
6fb6947feb | ||
|
db8173da28 | ||
|
bcdfb3cfb0 | ||
|
79aeb10431 | ||
|
5fd2b151b9 | ||
|
3c107ef4dc | ||
|
a5f93d6013 | ||
|
38338e848d | ||
|
e9518072a8 | ||
|
10dbd0afbd | ||
|
e22f938ae5 | ||
|
1dce56e2f8 | ||
|
1f0b2eac12 | ||
|
d9539e0f27 | ||
|
0909368339 | ||
|
091b634ea1 | ||
|
d18804b0bb | ||
|
a8b5b856d1 | ||
|
1d2a18b355 | ||
|
4a59340182 | ||
|
aa33613b98 | ||
|
cf042b2a4c | ||
|
65c86377fc | ||
|
96372c15e2 | ||
|
f365b32c60 | ||
|
5af2c42bde | ||
|
c0400e9db5 | ||
|
f7447837c5 | ||
|
a4dbee3e38 | ||
|
fb7899aa06 | ||
|
6d54d9f49a | ||
|
6546869c42 | ||
|
aa79a02f9c | ||
|
447febcdd6 | ||
|
61732847b6 | ||
|
fcd9d97f10 | ||
|
b6b5d52f78 | ||
|
4b6f29d5e1 | ||
|
f5d5230034 | ||
|
8dc19374cc | ||
|
a8f2af0503 | ||
|
d8a2941e9e | ||
|
55b6d0bbdd | ||
|
a3c044b657 | ||
|
4a2abc1a46 | ||
|
410c78f2e5 | ||
|
3b5830a1cf | ||
|
ab7df10a7d | ||
|
93663e987c | ||
|
6114266b84 | ||
|
97f96a6376 | ||
|
58062be2a3 | ||
|
031cf565ec | ||
|
5ec4efe88e | ||
|
e02aae71a1 | ||
|
1f9f885379 | ||
|
80509673d2 | ||
|
b902110d75 | ||
|
2c23027794 | ||
|
15589dd88f | ||
|
1a7f52c889 | ||
|
24cbf2287c | ||
|
a56d9de502 | ||
|
95e14ffb54 | ||
|
6139ee3add | ||
|
f0c0390646 | ||
|
e7a1949d85 | ||
|
ff8cb46bb9 | ||
|
399cb9707a | ||
|
6d9cd2d720 | ||
|
622537bd33 | ||
|
9169f840c2 | ||
|
79996b557b | ||
|
be8e5e1fdc | ||
|
bb0c3537cb | ||
|
36a5143478 | ||
|
7b86b87dca | ||
|
53affb9bc0 | ||
|
0fe2b66097 | ||
|
385f7f6e75 | ||
|
9f1e3db906 | ||
|
b63d900625 | ||
|
ac295de64c | ||
|
111571b67a | ||
|
a4bce333a3 | ||
|
c53a6eca86 | ||
|
7c2785e083 | ||
|
aab4149ab0 | ||
|
89a4b92753 | ||
|
5414a410bd | ||
|
ad796d188d | ||
|
de8cd5cd7f | ||
|
cc93c4fe12 | ||
|
c456a311d6 | ||
|
ed4b4b8482 | ||
|
8e4e3998dd | ||
|
8d9f207836 | ||
|
2a3164e040 | ||
|
f10d1327d4 | ||
|
d314174149 | ||
|
9885fe73dc | ||
|
f2cf323ecf | ||
|
cf4f2b4f14 | ||
|
fbc13ea6dc | ||
|
b8bc8eee41 | ||
|
11380769cd | ||
|
ee62c99eb1 | ||
|
843d439898 | ||
|
8d5da5cfca | ||
|
5a2c75a3cb | ||
|
c1e4cef75b | ||
|
5d73b9ccc5 | ||
|
9efe1fe09d | ||
|
4bbec963e6 | ||
|
348fc5b109 | ||
|
101864c050 | ||
|
fe150d4e4d | ||
|
048ac264a3 | ||
|
add7570a94 | ||
|
db77bd9588 | ||
|
768fe05eea | ||
|
1c48a001df | ||
|
a7276901a3 | ||
|
b0fa189b3c | ||
|
cc57152cc0 | ||
|
046f3eebcb | ||
|
ea874899c7 | ||
|
1782d19e1f | ||
|
e2476fbd0b | ||
|
07cd81ef58 | ||
|
92f542938c | ||
|
9df2306ee9 | ||
|
495d0b659a | ||
|
a2f8f17270 | ||
|
0e2329b59e | ||
|
7c011b14df | ||
|
ad68b23d8a | ||
|
670d977dfb | ||
|
70143d87bf | ||
|
e21ca5433a | ||
|
68ad4ff4d9 | ||
|
d7b0ff3de6 | ||
|
725f9ea3bd | ||
|
a9684648ab | ||
|
6b1dfa4ae6 | ||
|
9cc73bdf08 | ||
|
114ab5e4e6 | ||
|
77ebf4531c | ||
|
1551fe01f9 | ||
|
29874baf8a | ||
|
e6fe9d5807 | ||
|
81317505eb | ||
|
d57c27ffcf | ||
|
8d7b25d4f0 | ||
|
8e809aed01 | ||
|
b4c87c669b | ||
|
bca704e7e9 | ||
|
d50eb60827 | ||
|
dbd9aaf1ea | ||
|
d20d5e648f | ||
|
96640e68e2 | ||
|
3e007df97c | ||
|
06584ee3aa | ||
|
26e3142c95 | ||
|
33585fa673 | ||
|
665ce82d71 | ||
|
fb78bfaaae | ||
|
b4ce221002 | ||
|
444b1dafdc | ||
|
d6174b22e9 | ||
|
c75f394707 | ||
|
94ce99eb0a | ||
|
0515814e0c | ||
|
c87f4f613e | ||
|
f12e9fa22a | ||
|
3ca11b70c4 | ||
|
1cfaf927c9 | ||
|
45135ad3e4 | ||
|
9c06dd2863 | ||
|
b2088b72dd | ||
|
4e721bfd9d | ||
|
f52ed9f91e | ||
|
88f3b86410 | ||
|
3117858dcd | ||
|
8c36915ea0 | ||
|
5176e5c968 | ||
|
e95c733a81 | ||
|
15c2919ecc | ||
|
774f4dbbf7 | ||
|
b1e852a785 | ||
|
42ea4d2cfd | ||
|
9fd14cb6ea | ||
|
4e34803b1e | ||
|
7abcf6e0b9 | ||
|
e5ad0836bc | ||
|
2c50f20429 | ||
|
a15d626771 | ||
|
fd9b26675e | ||
|
eb33f085b6 | ||
|
fb774d4317 | ||
|
459bee6d2c | ||
|
6e080cd9b0 | ||
|
8a5ba6b20c | ||
|
c3ec3ff902 | ||
|
284a21012c | ||
|
7897c34ba3 | ||
|
8cc84e132a | ||
|
00ad151186 | ||
|
4265149463 | ||
|
ee8d6ab4fc | ||
|
a80745b5bd | ||
|
bd3f2d5cef | ||
|
e9c591e6de | ||
|
710d5ae48e | ||
|
fc769eb870 | ||
|
eec2ed5809 | ||
|
f7dd20f21c | ||
|
bfc9bcb8c7 | ||
|
8eb26c21be | ||
|
3c66e4cdba | ||
|
f0f2b81276 | ||
|
45ed6de315 | ||
|
c9290182be | ||
|
893538d8e6 | ||
|
246c8209c1 | ||
|
36fe2cb5ea | ||
|
9d6cc3a8d5 | ||
|
8870178a2d | ||
|
b0079ccd77 | ||
|
1772d122b2 | ||
|
756ae926ba | ||
|
2c1db56213 | ||
|
d672cef21c | ||
|
27e239c8d6 | ||
|
f1d7af11ee | ||
|
59a097b255 | ||
|
d40783022b | ||
|
7a3a473ccf | ||
|
2cdf752481 | ||
|
26f93feb2d | ||
|
d4aba0af48 | ||
|
42d12afbc6 | ||
|
022468ae3e | ||
|
3bb42cc66a | ||
|
8b5b27bb51 | ||
|
7328e0e1ac | ||
|
eeaf2ea4cf | ||
|
42eb8e4663 | ||
|
c13d0db0cc | ||
|
dba2026002 | ||
|
a62f74259c | ||
|
a2331fec55 | ||
|
b6872a0be3 | ||
|
bc7a73ca2c | ||
|
c405944e9d | ||
|
7eab889c07 | ||
|
bb55f68f95 | ||
|
658543c949 | ||
|
5b382668f5 | ||
|
b7692fad09 | ||
|
fbdda81515 | ||
|
7484888e42 | ||
|
f783a638a3 | ||
|
2d18e19263 | ||
|
ff7d489f2d | ||
|
6d29a5981c | ||
|
10b75d1d51 | ||
|
aa447585c4 | ||
|
f6c32c3ea3 | ||
|
d208896c46 | ||
|
08506f5139 | ||
|
2c4b11f321 | ||
|
d890d2f277 | ||
|
793f3990a0 | ||
|
9d439d2e5b | ||
|
db03f17486 | ||
|
dff78f616e | ||
|
d3a4d8dc24 | ||
|
dc58159d16 | ||
|
b60d5647a2 | ||
|
2bcfb3fea3 | ||
|
66f27ed1f3 | ||
|
cb84b93930 | ||
|
32a5453473 | ||
|
97d126ac8b | ||
|
deea7bb87b | ||
|
1bd1825ecb | ||
|
20e36191bb | ||
|
769566f36c | ||
|
ddd230485b | ||
|
5ee0cbaa42 | ||
|
ff675d40f9 | ||
|
0eebe43c08 | ||
|
069636e5b4 | ||
|
a03540dabc | ||
|
f6d69d0a00 | ||
|
cc2f26b8e9 | ||
|
3e687bbe9a | ||
|
c5113d3352 | ||
|
4d9712a3ef | ||
|
5b9b2c0973 | ||
|
a5af87758a | ||
|
8b11de5425 | ||
|
ff928e0e66 | ||
|
952191db99 | ||
|
61adca2a6d | ||
|
9872ed4bb2 | ||
|
3aa2d56da9 | ||
|
6a398724b6 | ||
|
af3823bced | ||
|
1e601bb2ef | ||
|
e4d240b1b7 | ||
|
e3470b28c5 | ||
|
e9a48770a7 | ||
|
0322b69f63 | ||
|
e587e82f7f | ||
|
5f5199bf53 | ||
|
876c4df1b6 | ||
|
e68ec257a3 | ||
|
216e0b2a52 | ||
|
ab0ff2ab3c | ||
|
5cd65f9c45 | ||
|
4e47c267fb | ||
|
cb47bbf753 | ||
|
c41d200a95 | ||
|
771d537ff3 | ||
|
8ca1f4ce44 | ||
|
625ec529ff | ||
|
caa81f3ac2 | ||
|
8092f57695 | ||
|
965a1234d3 | ||
|
15bc445a9c | ||
|
bb72de0dc9 | ||
|
6da0ecfa55 | ||
|
1ccc10baf8 | ||
|
45c2900e71 | ||
|
eb583dd2f3 | ||
|
f6233ffc9a | ||
|
46ee9faca9 | ||
|
f320b79c0c | ||
|
6cc05c103a | ||
|
88577b9889 | ||
|
5821f9748a | ||
|
c58bd33af7 | ||
|
cf7c60029b | ||
|
046e315bfd | ||
|
251800eb16 | ||
|
fe16fecd8f | ||
|
9ea9604b3f | ||
|
a32cd85eb7 | ||
|
95b460ae94 | ||
|
57e467c03c | ||
|
764a2fd5a8 | ||
|
d197130148 | ||
|
39d68822ed | ||
|
4ece73d432 | ||
|
60a217766f | ||
|
309240cd6f | ||
|
6b0d26ddf0 | ||
|
5aa8df163e | ||
|
881dc8172c | ||
|
aff441a01f | ||
|
44a14d0b3e | ||
|
f106bf5bc4 | ||
|
39b8336f3f | ||
|
a6bc284abd | ||
|
6b7b8a2303 | ||
|
8f20d90f88 | ||
|
047f098660 | ||
|
3b2554217b | ||
|
672d50393c | ||
|
d4467ab1c6 | ||
|
ebeb57ee7c | ||
|
f9355ea14d | ||
|
2ca6819cdf | ||
|
437372021d | ||
|
78ac01add7 | ||
|
3b3938c6a6 | ||
|
36fc05d2fd | ||
|
7abc747b56 | ||
|
9f976e568d | ||
|
9d7142f476 | ||
|
50f77cca1d | ||
|
33ebf124c4 | ||
|
03e162b342 | ||
|
d8b06f3e2f | ||
|
d6f206b5fd | ||
|
357a15ffd4 | ||
|
a3f892c76c | ||
|
2778ac61a4 | ||
|
c7b00caeaa | ||
|
7fe255e5bb | ||
|
93f7a26896 | ||
|
3d617fbf88 | ||
|
c59c3a1bcf | ||
|
4c0bf6225a | ||
|
b11662a887 | ||
|
11f1f71b3b | ||
|
0e9d1e09e3 | ||
|
65d2a3b0e5 | ||
|
8165da3f3d | ||
|
4b7347f1cd | ||
|
e6902d8ecc | ||
|
a5137affeb | ||
|
a423927ac9 | ||
|
31c2922752 | ||
|
7e81855e24 | ||
|
2510092599 | ||
|
6113a3f350 | ||
|
7d6fc1d680 | ||
|
91a101c855 | ||
|
1de127470f | ||
|
40de468413 | ||
|
c402feffbd | ||
|
f74d6b084b | ||
|
dd022f2dbc | ||
|
19928dea2b | ||
|
21273926ce | ||
|
c03bab3246 | ||
|
71347322d6 |
1520 changed files with 84369 additions and 29150 deletions
30
.ansible-lint
Normal file
30
.ansible-lint
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
parseable: true
|
||||||
|
skip_list:
|
||||||
|
# see https://docs.ansible.com/ansible-lint/rules/default_rules.html for a list of all default rules
|
||||||
|
|
||||||
|
# DO NOT add any other rules to this skip_list, instead use local `# noqa` with a comment explaining WHY it is necessary
|
||||||
|
|
||||||
|
# These rules are intentionally skipped:
|
||||||
|
#
|
||||||
|
# [E204]: "Lines should be no longer than 160 chars"
|
||||||
|
# This could be re-enabled with a major rewrite in the future.
|
||||||
|
# For now, there's not enough value gain from strictly limiting line length.
|
||||||
|
# (Disabled in May 2019)
|
||||||
|
- '204'
|
||||||
|
|
||||||
|
# [E701]: "meta/main.yml should contain relevant info"
|
||||||
|
# Roles in Kubespray are not intended to be used/imported by Ansible Galaxy.
|
||||||
|
# While it can be useful to have these metadata available, they are also available in the existing documentation.
|
||||||
|
# (Disabled in May 2019)
|
||||||
|
- '701'
|
||||||
|
|
||||||
|
# [role-name] "meta/main.yml" Role name role-name does not match ``^+$`` pattern
|
||||||
|
# Meta roles in Kubespray don't need proper names
|
||||||
|
# (Disabled in June 2021)
|
||||||
|
- 'role-name'
|
||||||
|
|
||||||
|
# [var-naming] "defaults/main.yml" File defines variable 'apiVersion' that violates variable naming standards
|
||||||
|
# In Kubespray we use variables that use camelCase to match their k8s counterparts
|
||||||
|
# (Disabled in June 2021)
|
||||||
|
- 'var-naming'
|
15
.editorconfig
Normal file
15
.editorconfig
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*.{yaml,yml,yml.j2,yaml.j2}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
charset = utf-8
|
||||||
|
|
||||||
|
[{Dockerfile}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
charset = utf-8
|
44
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
44
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
name: Bug Report
|
||||||
|
about: Report a bug encountered while operating Kubernetes
|
||||||
|
labels: kind/bug
|
||||||
|
|
||||||
|
---
|
||||||
|
<!--
|
||||||
|
Please, be ready for followup questions, and please respond in a timely
|
||||||
|
manner. If we can't reproduce a bug or think a feature already exists, we
|
||||||
|
might close your issue. If we're wrong, PLEASE feel free to reopen it and
|
||||||
|
explain why.
|
||||||
|
-->
|
||||||
|
|
||||||
|
**Environment**:
|
||||||
|
- **Cloud provider or hardware configuration:**
|
||||||
|
|
||||||
|
- **OS (`printf "$(uname -srm)\n$(cat /etc/os-release)\n"`):**
|
||||||
|
|
||||||
|
- **Version of Ansible** (`ansible --version`):
|
||||||
|
|
||||||
|
- **Version of Python** (`python --version`):
|
||||||
|
|
||||||
|
|
||||||
|
**Kubespray version (commit) (`git rev-parse --short HEAD`):**
|
||||||
|
|
||||||
|
|
||||||
|
**Network plugin used**:
|
||||||
|
|
||||||
|
|
||||||
|
**Full inventory with variables (`ansible -i inventory/sample/inventory.ini all -m debug -a "var=hostvars[inventory_hostname]"`):**
|
||||||
|
<!-- We recommend using snippets services like https://gist.github.com/ etc. -->
|
||||||
|
|
||||||
|
**Command used to invoke ansible**:
|
||||||
|
|
||||||
|
|
||||||
|
**Output of ansible run**:
|
||||||
|
<!-- We recommend using snippets services like https://gist.github.com/ etc. -->
|
||||||
|
|
||||||
|
**Anything else do we need to know**:
|
||||||
|
<!-- By running scripts/collect-info.yaml you can get a lot of useful informations.
|
||||||
|
Script can be started by:
|
||||||
|
ansible-playbook -i <inventory_file_path> -u <ssh_user> -e ansible_ssh_user=<ssh_user> -b --become-user=root -e dir=`pwd` scripts/collect-info.yaml
|
||||||
|
(If you using CoreOS remember to add '-e ansible_python_interpreter=/opt/bin/python').
|
||||||
|
After running this command you can find logs in `pwd`/logs.tar.gz. You can even upload somewhere entire file and paste link here.-->
|
11
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
name: Enhancement Request
|
||||||
|
about: Suggest an enhancement to the Kubespray project
|
||||||
|
labels: kind/feature
|
||||||
|
|
||||||
|
---
|
||||||
|
<!-- Please only use this template for submitting enhancement requests -->
|
||||||
|
|
||||||
|
**What would you like to be added**:
|
||||||
|
|
||||||
|
**Why is this needed**:
|
20
.github/ISSUE_TEMPLATE/failing-test.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/failing-test.md
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
name: Failing Test
|
||||||
|
about: Report test failures in Kubespray CI jobs
|
||||||
|
labels: kind/failing-test
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Please only use this template for submitting reports about failing tests in Kubespray CI jobs -->
|
||||||
|
|
||||||
|
**Which jobs are failing**:
|
||||||
|
|
||||||
|
**Which test(s) are failing**:
|
||||||
|
|
||||||
|
**Since when has it been failing**:
|
||||||
|
|
||||||
|
**Testgrid link**:
|
||||||
|
|
||||||
|
**Reason for failure**:
|
||||||
|
|
||||||
|
**Anything else we need to know**:
|
18
.github/ISSUE_TEMPLATE/support.md
vendored
Normal file
18
.github/ISSUE_TEMPLATE/support.md
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
name: Support Request
|
||||||
|
about: Support request or question relating to Kubespray
|
||||||
|
labels: kind/support
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
STOP -- PLEASE READ!
|
||||||
|
|
||||||
|
GitHub is not the right place for support requests.
|
||||||
|
|
||||||
|
If you're looking for help, check [Stack Overflow](https://stackoverflow.com/questions/tagged/kubespray) and the [troubleshooting guide](https://kubernetes.io/docs/tasks/debug-application-cluster/troubleshooting/).
|
||||||
|
|
||||||
|
You can also post your question on the [Kubernetes Slack](http://slack.k8s.io/) or the [Discuss Kubernetes](https://discuss.kubernetes.io/) forum.
|
||||||
|
|
||||||
|
If the matter is security related, please disclose it privately via https://kubernetes.io/security/.
|
||||||
|
-->
|
44
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
44
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<!-- Thanks for sending a pull request! Here are some tips for you:
|
||||||
|
|
||||||
|
1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide/first-contribution.md and developer guide https://git.k8s.io/community/contributors/devel/development.md
|
||||||
|
2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. For reference on required PR/issue labels, read here:
|
||||||
|
https://git.k8s.io/community/contributors/devel/sig-release/release.md#issuepr-kind-label
|
||||||
|
3. Ensure you have added or ran the appropriate tests for your PR: https://git.k8s.io/community/contributors/devel/sig-testing/testing.md
|
||||||
|
4. If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews
|
||||||
|
5. Follow the instructions for writing a release note: https://git.k8s.io/community/contributors/guide/release-notes.md
|
||||||
|
6. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
|
||||||
|
-->
|
||||||
|
|
||||||
|
**What type of PR is this?**
|
||||||
|
> Uncomment only one ` /kind <>` line, hit enter to put that in a new line, and remove leading whitespaces from that line:
|
||||||
|
>
|
||||||
|
> /kind api-change
|
||||||
|
> /kind bug
|
||||||
|
> /kind cleanup
|
||||||
|
> /kind design
|
||||||
|
> /kind documentation
|
||||||
|
> /kind failing-test
|
||||||
|
> /kind feature
|
||||||
|
> /kind flake
|
||||||
|
|
||||||
|
**What this PR does / why we need it**:
|
||||||
|
|
||||||
|
**Which issue(s) this PR fixes**:
|
||||||
|
<!--
|
||||||
|
*Automatically closes linked issue when PR is merged.
|
||||||
|
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
|
||||||
|
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
|
||||||
|
-->
|
||||||
|
Fixes #
|
||||||
|
|
||||||
|
**Special notes for your reviewer**:
|
||||||
|
|
||||||
|
**Does this PR introduce a user-facing change?**:
|
||||||
|
<!--
|
||||||
|
If no, just write "NONE" in the release-note block below.
|
||||||
|
If yes, a release note is required:
|
||||||
|
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
|
||||||
|
-->
|
||||||
|
```release-note
|
||||||
|
|
||||||
|
```
|
114
.gitignore
vendored
114
.gitignore
vendored
|
@ -1,5 +1,117 @@
|
||||||
.vagrant
|
.vagrant
|
||||||
*.retry
|
*.retry
|
||||||
inventory/vagrant_ansible_inventory
|
**/vagrant_ansible_inventory
|
||||||
|
*.iml
|
||||||
temp
|
temp
|
||||||
|
contrib/offline/offline-files
|
||||||
|
contrib/offline/offline-files.tar.gz
|
||||||
.idea
|
.idea
|
||||||
|
.vscode
|
||||||
|
.tox
|
||||||
|
.cache
|
||||||
|
*.bak
|
||||||
|
*.tfstate
|
||||||
|
*.tfstate.backup
|
||||||
|
.terraform/
|
||||||
|
contrib/terraform/aws/credentials.tfvars
|
||||||
|
.terraform.lock.hcl
|
||||||
|
/ssh-bastion.conf
|
||||||
|
**/*.sw[pon]
|
||||||
|
*~
|
||||||
|
vagrant/
|
||||||
|
plugins/mitogen
|
||||||
|
deploy.sh
|
||||||
|
|
||||||
|
# Ansible inventory
|
||||||
|
inventory/*
|
||||||
|
!inventory/local
|
||||||
|
!inventory/sample
|
||||||
|
!inventory/c12s-sample
|
||||||
|
inventory/*/artifacts/
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
env/
|
||||||
|
build/
|
||||||
|
credentials/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*,cover
|
||||||
|
.hypothesis/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# IPython Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# dotenv
|
||||||
|
.env
|
||||||
|
|
||||||
|
# virtualenv
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# molecule
|
||||||
|
roles/**/molecule/**/__pycache__/
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Temp location used by our scripts
|
||||||
|
scripts/tmp/
|
||||||
|
tmp.md
|
||||||
|
|
84
.gitlab-ci.yml
Normal file
84
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
---
|
||||||
|
stages:
|
||||||
|
- unit-tests
|
||||||
|
- deploy-part1
|
||||||
|
- moderator
|
||||||
|
- deploy-part2
|
||||||
|
- deploy-part3
|
||||||
|
- deploy-special
|
||||||
|
|
||||||
|
variables:
|
||||||
|
KUBESPRAY_VERSION: v2.20.0
|
||||||
|
FAILFASTCI_NAMESPACE: 'kargo-ci'
|
||||||
|
GITLAB_REPOSITORY: 'kargo-ci/kubernetes-sigs-kubespray'
|
||||||
|
ANSIBLE_FORCE_COLOR: "true"
|
||||||
|
MAGIC: "ci check this"
|
||||||
|
TEST_ID: "$CI_PIPELINE_ID-$CI_BUILD_ID"
|
||||||
|
CI_TEST_VARS: "./tests/files/${CI_JOB_NAME}.yml"
|
||||||
|
CI_TEST_REGISTRY_MIRROR: "./tests/common/_docker_hub_registry_mirror.yml"
|
||||||
|
CI_TEST_SETTING: "./tests/common/_kubespray_test_settings.yml"
|
||||||
|
GS_ACCESS_KEY_ID: $GS_KEY
|
||||||
|
GS_SECRET_ACCESS_KEY: $GS_SECRET
|
||||||
|
CONTAINER_ENGINE: docker
|
||||||
|
SSH_USER: root
|
||||||
|
GCE_PREEMPTIBLE: "false"
|
||||||
|
ANSIBLE_KEEP_REMOTE_FILES: "1"
|
||||||
|
ANSIBLE_CONFIG: ./tests/ansible.cfg
|
||||||
|
ANSIBLE_INVENTORY: ./inventory/sample/${CI_JOB_NAME}-${BUILD_NUMBER}.ini
|
||||||
|
IDEMPOT_CHECK: "false"
|
||||||
|
RESET_CHECK: "false"
|
||||||
|
REMOVE_NODE_CHECK: "false"
|
||||||
|
UPGRADE_TEST: "false"
|
||||||
|
MITOGEN_ENABLE: "false"
|
||||||
|
ANSIBLE_LOG_LEVEL: "-vv"
|
||||||
|
RECOVER_CONTROL_PLANE_TEST: "false"
|
||||||
|
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube_control_plane[1:]"
|
||||||
|
TERRAFORM_VERSION: 1.0.8
|
||||||
|
ANSIBLE_MAJOR_VERSION: "2.11"
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- ./tests/scripts/rebase.sh
|
||||||
|
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1
|
||||||
|
- python -m pip uninstall -y ansible ansible-base ansible-core
|
||||||
|
- python -m pip install -r tests/requirements-${ANSIBLE_MAJOR_VERSION}.txt
|
||||||
|
- mkdir -p /.ssh
|
||||||
|
|
||||||
|
.job: &job
|
||||||
|
tags:
|
||||||
|
- packet
|
||||||
|
image: quay.io/kubespray/kubespray:$KUBESPRAY_VERSION
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- cluster-dump/
|
||||||
|
|
||||||
|
.testcases: &testcases
|
||||||
|
<<: *job
|
||||||
|
retry: 1
|
||||||
|
before_script:
|
||||||
|
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1
|
||||||
|
- ./tests/scripts/rebase.sh
|
||||||
|
- ./tests/scripts/testcases_prepare.sh
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/testcases_run.sh
|
||||||
|
after_script:
|
||||||
|
- chronic ./tests/scripts/testcases_cleanup.sh
|
||||||
|
|
||||||
|
# For failfast, at least 1 job must be defined in .gitlab-ci.yml
|
||||||
|
# Premoderated with manual actions
|
||||||
|
ci-authorized:
|
||||||
|
extends: .job
|
||||||
|
stage: moderator
|
||||||
|
script:
|
||||||
|
- /bin/sh scripts/premoderator.sh
|
||||||
|
except: ['triggers', 'master']
|
||||||
|
# Disable ci moderator
|
||||||
|
only: []
|
||||||
|
|
||||||
|
include:
|
||||||
|
- .gitlab-ci/lint.yml
|
||||||
|
- .gitlab-ci/shellcheck.yml
|
||||||
|
- .gitlab-ci/terraform.yml
|
||||||
|
- .gitlab-ci/packet.yml
|
||||||
|
- .gitlab-ci/vagrant.yml
|
||||||
|
- .gitlab-ci/molecule.yml
|
90
.gitlab-ci/lint.yml
Normal file
90
.gitlab-ci/lint.yml
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
---
|
||||||
|
yamllint:
|
||||||
|
extends: .job
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
variables:
|
||||||
|
LANG: C.UTF-8
|
||||||
|
script:
|
||||||
|
- yamllint --strict .
|
||||||
|
except: ['triggers', 'master']
|
||||||
|
|
||||||
|
vagrant-validate:
|
||||||
|
extends: .job
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
variables:
|
||||||
|
VAGRANT_VERSION: 2.2.19
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/vagrant-validate.sh
|
||||||
|
except: ['triggers', 'master']
|
||||||
|
|
||||||
|
ansible-lint:
|
||||||
|
extends: .job
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
script:
|
||||||
|
- ansible-lint -v
|
||||||
|
except: ['triggers', 'master']
|
||||||
|
|
||||||
|
syntax-check:
|
||||||
|
extends: .job
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
variables:
|
||||||
|
ANSIBLE_INVENTORY: inventory/local-tests.cfg
|
||||||
|
ANSIBLE_REMOTE_USER: root
|
||||||
|
ANSIBLE_BECOME: "true"
|
||||||
|
ANSIBLE_BECOME_USER: root
|
||||||
|
ANSIBLE_VERBOSITY: "3"
|
||||||
|
script:
|
||||||
|
- ansible-playbook --syntax-check cluster.yml
|
||||||
|
- ansible-playbook --syntax-check upgrade-cluster.yml
|
||||||
|
- ansible-playbook --syntax-check reset.yml
|
||||||
|
- ansible-playbook --syntax-check extra_playbooks/upgrade-only-k8s.yml
|
||||||
|
except: ['triggers', 'master']
|
||||||
|
|
||||||
|
tox-inventory-builder:
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
extends: .job
|
||||||
|
before_script:
|
||||||
|
- ./tests/scripts/rebase.sh
|
||||||
|
- apt-get update && apt-get install -y python3-pip
|
||||||
|
- update-alternatives --install /usr/bin/python python /usr/bin/python3 10
|
||||||
|
- python -m pip uninstall -y ansible ansible-base ansible-core
|
||||||
|
- python -m pip install -r tests/requirements.txt
|
||||||
|
script:
|
||||||
|
- pip3 install tox
|
||||||
|
- cd contrib/inventory_builder && tox
|
||||||
|
except: ['triggers', 'master']
|
||||||
|
|
||||||
|
markdownlint:
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
image: node
|
||||||
|
before_script:
|
||||||
|
- npm install -g markdownlint-cli@0.22.0
|
||||||
|
script:
|
||||||
|
- markdownlint $(find . -name '*.md' | grep -vF './.git') --ignore docs/_sidebar.md --ignore contrib/dind/README.md
|
||||||
|
|
||||||
|
check-readme-versions:
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
image: python:3
|
||||||
|
script:
|
||||||
|
- tests/scripts/check_readme_versions.sh
|
||||||
|
|
||||||
|
check-typo:
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
image: python:3
|
||||||
|
script:
|
||||||
|
- tests/scripts/check_typo.sh
|
||||||
|
|
||||||
|
ci-matrix:
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
image: python:3
|
||||||
|
script:
|
||||||
|
- tests/scripts/md-table/test.sh
|
86
.gitlab-ci/molecule.yml
Normal file
86
.gitlab-ci/molecule.yml
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
.molecule:
|
||||||
|
tags: [c3.small.x86]
|
||||||
|
only: [/^pr-.*$/]
|
||||||
|
except: ['triggers']
|
||||||
|
image: quay.io/kubespray/vagrant:$KUBESPRAY_VERSION
|
||||||
|
services: []
|
||||||
|
stage: deploy-part1
|
||||||
|
before_script:
|
||||||
|
- tests/scripts/rebase.sh
|
||||||
|
- apt-get update && apt-get install -y python3-pip
|
||||||
|
- update-alternatives --install /usr/bin/python python /usr/bin/python3 10
|
||||||
|
- python -m pip uninstall -y ansible ansible-base ansible-core
|
||||||
|
- python -m pip install -r tests/requirements.txt
|
||||||
|
- ./tests/scripts/vagrant_clean.sh
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/molecule_run.sh
|
||||||
|
after_script:
|
||||||
|
- chronic ./tests/scripts/molecule_logs.sh
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- molecule_logs/
|
||||||
|
|
||||||
|
# CI template for periodic CI jobs
|
||||||
|
# Enabled when PERIODIC_CI_ENABLED var is set
|
||||||
|
.molecule_periodic:
|
||||||
|
only:
|
||||||
|
variables:
|
||||||
|
- $PERIODIC_CI_ENABLED
|
||||||
|
allow_failure: true
|
||||||
|
extends: .molecule
|
||||||
|
|
||||||
|
molecule_full:
|
||||||
|
extends: .molecule_periodic
|
||||||
|
|
||||||
|
molecule_no_container_engines:
|
||||||
|
extends: .molecule
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/molecule_run.sh -e container-engine
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
molecule_docker:
|
||||||
|
extends: .molecule
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/molecule_run.sh -i container-engine/cri-dockerd
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
molecule_containerd:
|
||||||
|
extends: .molecule
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/molecule_run.sh -i container-engine/containerd
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
molecule_cri-o:
|
||||||
|
extends: .molecule
|
||||||
|
stage: deploy-part2
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/molecule_run.sh -i container-engine/cri-o
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
# Stage 3 container engines don't get as much attention so allow them to fail
|
||||||
|
molecule_kata:
|
||||||
|
extends: .molecule
|
||||||
|
stage: deploy-part3
|
||||||
|
allow_failure: true
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/molecule_run.sh -i container-engine/kata-containers
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
molecule_gvisor:
|
||||||
|
extends: .molecule
|
||||||
|
stage: deploy-part3
|
||||||
|
allow_failure: true
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/molecule_run.sh -i container-engine/gvisor
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
molecule_youki:
|
||||||
|
extends: .molecule
|
||||||
|
stage: deploy-part3
|
||||||
|
allow_failure: true
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/molecule_run.sh -i container-engine/youki
|
||||||
|
when: on_success
|
328
.gitlab-ci/packet.yml
Normal file
328
.gitlab-ci/packet.yml
Normal file
|
@ -0,0 +1,328 @@
|
||||||
|
---
|
||||||
|
.packet:
|
||||||
|
extends: .testcases
|
||||||
|
variables:
|
||||||
|
ANSIBLE_TIMEOUT: "120"
|
||||||
|
CI_PLATFORM: packet
|
||||||
|
SSH_USER: kubespray
|
||||||
|
tags:
|
||||||
|
- packet
|
||||||
|
except: [triggers]
|
||||||
|
|
||||||
|
# CI template for PRs
|
||||||
|
.packet_pr:
|
||||||
|
only: [/^pr-.*$/]
|
||||||
|
extends: .packet
|
||||||
|
|
||||||
|
# CI template for periodic CI jobs
|
||||||
|
# Enabled when PERIODIC_CI_ENABLED var is set
|
||||||
|
.packet_periodic:
|
||||||
|
only:
|
||||||
|
variables:
|
||||||
|
- $PERIODIC_CI_ENABLED
|
||||||
|
allow_failure: true
|
||||||
|
extends: .packet
|
||||||
|
|
||||||
|
# The ubuntu20-calico-aio jobs are meant as early stages to prevent running the full CI if something is horribly broken
|
||||||
|
packet_ubuntu20-calico-aio:
|
||||||
|
stage: deploy-part1
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
RESET_CHECK: "true"
|
||||||
|
|
||||||
|
packet_ubuntu20-calico-aio-ansible-2_11:
|
||||||
|
stage: deploy-part1
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
ANSIBLE_MAJOR_VERSION: "2.11"
|
||||||
|
RESET_CHECK: "true"
|
||||||
|
|
||||||
|
# ### PR JOBS PART2
|
||||||
|
|
||||||
|
packet_ubuntu18-aio-docker:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_ubuntu20-aio-docker:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_ubuntu20-calico-aio-hardening:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_ubuntu18-calico-aio:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_ubuntu22-aio-docker:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_ubuntu22-calico-aio:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_centos7-flannel-addons-ha:
|
||||||
|
extends: .packet_pr
|
||||||
|
stage: deploy-part2
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_almalinux8-crio:
|
||||||
|
extends: .packet_pr
|
||||||
|
stage: deploy-part2
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_ubuntu18-crio:
|
||||||
|
extends: .packet_pr
|
||||||
|
stage: deploy-part2
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_fedora35-crio:
|
||||||
|
extends: .packet_pr
|
||||||
|
stage: deploy-part2
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_ubuntu16-canal-ha:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_ubuntu16-canal-sep:
|
||||||
|
stage: deploy-special
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_ubuntu16-flannel-ha:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_debian10-cilium-svc-proxy:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_debian10-calico:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_debian10-docker:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_debian11-calico:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_debian11-docker:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_centos7-calico-ha-once-localhost:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
# This will instruct Docker not to start over TLS.
|
||||||
|
DOCKER_TLS_CERTDIR: ""
|
||||||
|
services:
|
||||||
|
- docker:19.03.9-dind
|
||||||
|
|
||||||
|
packet_almalinux8-kube-ovn:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_almalinux8-calico:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_rockylinux8-calico:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_rockylinux9-calico:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_almalinux8-docker:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_fedora36-docker-weave:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_opensuse-canal:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_opensuse-docker-cilium:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
# ### MANUAL JOBS
|
||||||
|
|
||||||
|
packet_ubuntu16-docker-weave-sep:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_ubuntu18-cilium-sep:
|
||||||
|
stage: deploy-special
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_ubuntu18-flannel-ha:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_ubuntu18-flannel-ha-once:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
# Calico HA eBPF
|
||||||
|
packet_almalinux8-calico-ha-ebpf:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_debian9-macvlan:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_centos7-calico-ha:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_centos7-multus-calico:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_centos7-canal-ha:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_fedora36-docker-calico:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
RESET_CHECK: "true"
|
||||||
|
|
||||||
|
packet_fedora35-calico-selinux:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_fedora35-calico-swap-selinux:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_amazon-linux-2-aio:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_almalinux8-calico-nodelocaldns-secondary:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_fedora36-kube-ovn:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
# ### PR JOBS PART3
|
||||||
|
# Long jobs (45min+)
|
||||||
|
|
||||||
|
packet_centos7-weave-upgrade-ha:
|
||||||
|
stage: deploy-part3
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
UPGRADE_TEST: basic
|
||||||
|
|
||||||
|
packet_ubuntu20-calico-etcd-kubeadm-upgrade-ha:
|
||||||
|
stage: deploy-part3
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
UPGRADE_TEST: basic
|
||||||
|
|
||||||
|
# Calico HA Wireguard
|
||||||
|
packet_ubuntu20-calico-ha-wireguard:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .packet_pr
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
packet_debian11-calico-upgrade:
|
||||||
|
stage: deploy-part3
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
UPGRADE_TEST: graceful
|
||||||
|
|
||||||
|
packet_almalinux8-calico-remove-node:
|
||||||
|
stage: deploy-part3
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
REMOVE_NODE_CHECK: "true"
|
||||||
|
REMOVE_NODE_NAME: "instance-3"
|
||||||
|
|
||||||
|
packet_ubuntu20-calico-etcd-kubeadm:
|
||||||
|
stage: deploy-part3
|
||||||
|
extends: .packet_pr
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
packet_debian11-calico-upgrade-once:
|
||||||
|
stage: deploy-part3
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
UPGRADE_TEST: graceful
|
||||||
|
|
||||||
|
packet_ubuntu18-calico-ha-recover:
|
||||||
|
stage: deploy-part3
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
RECOVER_CONTROL_PLANE_TEST: "true"
|
||||||
|
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[2:],kube_control_plane[1:]"
|
||||||
|
|
||||||
|
packet_ubuntu18-calico-ha-recover-noquorum:
|
||||||
|
stage: deploy-part3
|
||||||
|
extends: .packet_periodic
|
||||||
|
when: on_success
|
||||||
|
variables:
|
||||||
|
RECOVER_CONTROL_PLANE_TEST: "true"
|
||||||
|
RECOVER_CONTROL_PLANE_TEST_GROUPS: "etcd[1:],kube_control_plane[1:]"
|
16
.gitlab-ci/shellcheck.yml
Normal file
16
.gitlab-ci/shellcheck.yml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
shellcheck:
|
||||||
|
extends: .job
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
variables:
|
||||||
|
SHELLCHECK_VERSION: v0.7.1
|
||||||
|
before_script:
|
||||||
|
- ./tests/scripts/rebase.sh
|
||||||
|
- curl --silent --location "https://github.com/koalaman/shellcheck/releases/download/"${SHELLCHECK_VERSION}"/shellcheck-"${SHELLCHECK_VERSION}".linux.x86_64.tar.xz" | tar -xJv
|
||||||
|
- cp shellcheck-"${SHELLCHECK_VERSION}"/shellcheck /usr/bin/
|
||||||
|
- shellcheck --version
|
||||||
|
script:
|
||||||
|
# Run shellcheck for all *.sh
|
||||||
|
- find . -name '*.sh' -not -path './.git/*' | xargs shellcheck --severity error
|
||||||
|
except: ['triggers', 'master']
|
235
.gitlab-ci/terraform.yml
Normal file
235
.gitlab-ci/terraform.yml
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
---
|
||||||
|
# Tests for contrib/terraform/
|
||||||
|
.terraform_install:
|
||||||
|
extends: .job
|
||||||
|
before_script:
|
||||||
|
- update-alternatives --install /usr/bin/python python /usr/bin/python3 1
|
||||||
|
- ./tests/scripts/rebase.sh
|
||||||
|
- ./tests/scripts/testcases_prepare.sh
|
||||||
|
- ./tests/scripts/terraform_install.sh
|
||||||
|
# Set Ansible config
|
||||||
|
- cp ansible.cfg ~/.ansible.cfg
|
||||||
|
# Prepare inventory
|
||||||
|
- cp contrib/terraform/$PROVIDER/sample-inventory/cluster.tfvars .
|
||||||
|
- ln -s contrib/terraform/$PROVIDER/hosts
|
||||||
|
- terraform -chdir="contrib/terraform/$PROVIDER" init
|
||||||
|
# Copy SSH keypair
|
||||||
|
- mkdir -p ~/.ssh
|
||||||
|
- echo "$PACKET_PRIVATE_KEY" | base64 -d > ~/.ssh/id_rsa
|
||||||
|
- chmod 400 ~/.ssh/id_rsa
|
||||||
|
- echo "$PACKET_PUBLIC_KEY" | base64 -d > ~/.ssh/id_rsa.pub
|
||||||
|
- mkdir -p contrib/terraform/$PROVIDER/group_vars
|
||||||
|
# Random subnet to avoid routing conflicts
|
||||||
|
- export TF_VAR_subnet_cidr="10.$(( $RANDOM % 256 )).$(( $RANDOM % 256 )).0/24"
|
||||||
|
|
||||||
|
.terraform_validate:
|
||||||
|
extends: .terraform_install
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
only: ['master', /^pr-.*$/]
|
||||||
|
script:
|
||||||
|
- terraform -chdir="contrib/terraform/$PROVIDER" validate
|
||||||
|
- terraform -chdir="contrib/terraform/$PROVIDER" fmt -check -diff
|
||||||
|
|
||||||
|
.terraform_apply:
|
||||||
|
extends: .terraform_install
|
||||||
|
tags: [light]
|
||||||
|
stage: deploy-part3
|
||||||
|
when: manual
|
||||||
|
only: [/^pr-.*$/]
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- cluster-dump/
|
||||||
|
variables:
|
||||||
|
ANSIBLE_INVENTORY_UNPARSED_FAILED: "true"
|
||||||
|
ANSIBLE_INVENTORY: hosts
|
||||||
|
CI_PLATFORM: tf
|
||||||
|
TF_VAR_ssh_user: $SSH_USER
|
||||||
|
TF_VAR_cluster_name: $CI_JOB_ID
|
||||||
|
script:
|
||||||
|
- tests/scripts/testcases_run.sh
|
||||||
|
after_script:
|
||||||
|
# Cleanup regardless of exit code
|
||||||
|
- chronic ./tests/scripts/testcases_cleanup.sh
|
||||||
|
|
||||||
|
tf-validate-openstack:
|
||||||
|
extends: .terraform_validate
|
||||||
|
variables:
|
||||||
|
TF_VERSION: $TERRAFORM_VERSION
|
||||||
|
PROVIDER: openstack
|
||||||
|
CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
|
tf-validate-metal:
|
||||||
|
extends: .terraform_validate
|
||||||
|
variables:
|
||||||
|
TF_VERSION: $TERRAFORM_VERSION
|
||||||
|
PROVIDER: metal
|
||||||
|
CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
|
tf-validate-aws:
|
||||||
|
extends: .terraform_validate
|
||||||
|
variables:
|
||||||
|
TF_VERSION: $TERRAFORM_VERSION
|
||||||
|
PROVIDER: aws
|
||||||
|
CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
|
tf-validate-exoscale:
|
||||||
|
extends: .terraform_validate
|
||||||
|
variables:
|
||||||
|
TF_VERSION: $TERRAFORM_VERSION
|
||||||
|
PROVIDER: exoscale
|
||||||
|
|
||||||
|
tf-validate-vsphere:
|
||||||
|
extends: .terraform_validate
|
||||||
|
variables:
|
||||||
|
TF_VERSION: $TERRAFORM_VERSION
|
||||||
|
PROVIDER: vsphere
|
||||||
|
CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
|
tf-validate-upcloud:
|
||||||
|
extends: .terraform_validate
|
||||||
|
variables:
|
||||||
|
TF_VERSION: $TERRAFORM_VERSION
|
||||||
|
PROVIDER: upcloud
|
||||||
|
CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
|
# tf-packet-ubuntu16-default:
|
||||||
|
# extends: .terraform_apply
|
||||||
|
# variables:
|
||||||
|
# TF_VERSION: $TERRAFORM_VERSION
|
||||||
|
# PROVIDER: packet
|
||||||
|
# CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
# TF_VAR_number_of_k8s_masters: "1"
|
||||||
|
# TF_VAR_number_of_k8s_nodes: "1"
|
||||||
|
# TF_VAR_plan_k8s_masters: t1.small.x86
|
||||||
|
# TF_VAR_plan_k8s_nodes: t1.small.x86
|
||||||
|
# TF_VAR_facility: ewr1
|
||||||
|
# TF_VAR_public_key_path: ""
|
||||||
|
# TF_VAR_operating_system: ubuntu_16_04
|
||||||
|
#
|
||||||
|
# tf-packet-ubuntu18-default:
|
||||||
|
# extends: .terraform_apply
|
||||||
|
# variables:
|
||||||
|
# TF_VERSION: $TERRAFORM_VERSION
|
||||||
|
# PROVIDER: packet
|
||||||
|
# CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
# TF_VAR_number_of_k8s_masters: "1"
|
||||||
|
# TF_VAR_number_of_k8s_nodes: "1"
|
||||||
|
# TF_VAR_plan_k8s_masters: t1.small.x86
|
||||||
|
# TF_VAR_plan_k8s_nodes: t1.small.x86
|
||||||
|
# TF_VAR_facility: ams1
|
||||||
|
# TF_VAR_public_key_path: ""
|
||||||
|
# TF_VAR_operating_system: ubuntu_18_04
|
||||||
|
|
||||||
|
.ovh_variables: &ovh_variables
|
||||||
|
OS_AUTH_URL: https://auth.cloud.ovh.net/v3
|
||||||
|
OS_PROJECT_ID: 8d3cd5d737d74227ace462dee0b903fe
|
||||||
|
OS_PROJECT_NAME: "9361447987648822"
|
||||||
|
OS_USER_DOMAIN_NAME: Default
|
||||||
|
OS_PROJECT_DOMAIN_ID: default
|
||||||
|
OS_USERNAME: 8XuhBMfkKVrk
|
||||||
|
OS_REGION_NAME: UK1
|
||||||
|
OS_INTERFACE: public
|
||||||
|
OS_IDENTITY_API_VERSION: "3"
|
||||||
|
|
||||||
|
# Elastx is generously donating resources for Kubespray on Openstack CI
|
||||||
|
# Contacts: @gix @bl0m1
|
||||||
|
.elastx_variables: &elastx_variables
|
||||||
|
OS_AUTH_URL: https://ops.elastx.cloud:5000
|
||||||
|
OS_PROJECT_ID: 564c6b461c6b44b1bb19cdb9c2d928e4
|
||||||
|
OS_PROJECT_NAME: kubespray_ci
|
||||||
|
OS_USER_DOMAIN_NAME: Default
|
||||||
|
OS_PROJECT_DOMAIN_ID: default
|
||||||
|
OS_USERNAME: kubespray@root314.com
|
||||||
|
OS_REGION_NAME: se-sto
|
||||||
|
OS_INTERFACE: public
|
||||||
|
OS_IDENTITY_API_VERSION: "3"
|
||||||
|
TF_VAR_router_id: "ab95917c-41fb-4881-b507-3a6dfe9403df"
|
||||||
|
|
||||||
|
tf-elastx_cleanup:
|
||||||
|
stage: unit-tests
|
||||||
|
tags: [light]
|
||||||
|
image: python
|
||||||
|
variables:
|
||||||
|
<<: *elastx_variables
|
||||||
|
before_script:
|
||||||
|
- pip install -r scripts/openstack-cleanup/requirements.txt
|
||||||
|
script:
|
||||||
|
- ./scripts/openstack-cleanup/main.py
|
||||||
|
|
||||||
|
tf-elastx_ubuntu18-calico:
|
||||||
|
extends: .terraform_apply
|
||||||
|
stage: deploy-part3
|
||||||
|
when: on_success
|
||||||
|
allow_failure: true
|
||||||
|
variables:
|
||||||
|
<<: *elastx_variables
|
||||||
|
TF_VERSION: $TERRAFORM_VERSION
|
||||||
|
PROVIDER: openstack
|
||||||
|
CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
ANSIBLE_TIMEOUT: "60"
|
||||||
|
SSH_USER: ubuntu
|
||||||
|
TF_VAR_number_of_k8s_masters: "1"
|
||||||
|
TF_VAR_number_of_k8s_masters_no_floating_ip: "0"
|
||||||
|
TF_VAR_number_of_k8s_masters_no_floating_ip_no_etcd: "0"
|
||||||
|
TF_VAR_number_of_etcd: "0"
|
||||||
|
TF_VAR_number_of_k8s_nodes: "1"
|
||||||
|
TF_VAR_number_of_k8s_nodes_no_floating_ip: "0"
|
||||||
|
TF_VAR_number_of_gfs_nodes_no_floating_ip: "0"
|
||||||
|
TF_VAR_number_of_bastions: "0"
|
||||||
|
TF_VAR_number_of_k8s_masters_no_etcd: "0"
|
||||||
|
TF_VAR_floatingip_pool: "elx-public1"
|
||||||
|
TF_VAR_dns_nameservers: '["1.1.1.1", "8.8.8.8", "8.8.4.4"]'
|
||||||
|
TF_VAR_use_access_ip: "0"
|
||||||
|
TF_VAR_external_net: "600b8501-78cb-4155-9c9f-23dfcba88828"
|
||||||
|
TF_VAR_network_name: "ci-$CI_JOB_ID"
|
||||||
|
TF_VAR_az_list: '["sto1"]'
|
||||||
|
TF_VAR_az_list_node: '["sto1"]'
|
||||||
|
TF_VAR_flavor_k8s_master: 3f73fc93-ec61-4808-88df-2580d94c1a9b # v1-standard-2
|
||||||
|
TF_VAR_flavor_k8s_node: 3f73fc93-ec61-4808-88df-2580d94c1a9b # v1-standard-2
|
||||||
|
TF_VAR_image: ubuntu-18.04-server-latest
|
||||||
|
TF_VAR_k8s_allowed_remote_ips: '["0.0.0.0/0"]'
|
||||||
|
|
||||||
|
# OVH voucher expired, commenting job until things are sorted out
|
||||||
|
|
||||||
|
# tf-ovh_cleanup:
|
||||||
|
# stage: unit-tests
|
||||||
|
# tags: [light]
|
||||||
|
# image: python
|
||||||
|
# environment: ovh
|
||||||
|
# variables:
|
||||||
|
# <<: *ovh_variables
|
||||||
|
# before_script:
|
||||||
|
# - pip install -r scripts/openstack-cleanup/requirements.txt
|
||||||
|
# script:
|
||||||
|
# - ./scripts/openstack-cleanup/main.py
|
||||||
|
|
||||||
|
# tf-ovh_ubuntu18-calico:
|
||||||
|
# extends: .terraform_apply
|
||||||
|
# when: on_success
|
||||||
|
# environment: ovh
|
||||||
|
# variables:
|
||||||
|
# <<: *ovh_variables
|
||||||
|
# TF_VERSION: $TERRAFORM_VERSION
|
||||||
|
# PROVIDER: openstack
|
||||||
|
# CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
# ANSIBLE_TIMEOUT: "60"
|
||||||
|
# SSH_USER: ubuntu
|
||||||
|
# TF_VAR_number_of_k8s_masters: "0"
|
||||||
|
# TF_VAR_number_of_k8s_masters_no_floating_ip: "1"
|
||||||
|
# TF_VAR_number_of_k8s_masters_no_floating_ip_no_etcd: "0"
|
||||||
|
# TF_VAR_number_of_etcd: "0"
|
||||||
|
# TF_VAR_number_of_k8s_nodes: "0"
|
||||||
|
# TF_VAR_number_of_k8s_nodes_no_floating_ip: "1"
|
||||||
|
# TF_VAR_number_of_gfs_nodes_no_floating_ip: "0"
|
||||||
|
# TF_VAR_number_of_bastions: "0"
|
||||||
|
# TF_VAR_number_of_k8s_masters_no_etcd: "0"
|
||||||
|
# TF_VAR_use_neutron: "0"
|
||||||
|
# TF_VAR_floatingip_pool: "Ext-Net"
|
||||||
|
# TF_VAR_external_net: "6011fbc9-4cbf-46a4-8452-6890a340b60b"
|
||||||
|
# TF_VAR_network_name: "Ext-Net"
|
||||||
|
# TF_VAR_flavor_k8s_master: "defa64c3-bd46-43b4-858a-d93bbae0a229" # s1-8
|
||||||
|
# TF_VAR_flavor_k8s_node: "defa64c3-bd46-43b4-858a-d93bbae0a229" # s1-8
|
||||||
|
# TF_VAR_image: "Ubuntu 18.04"
|
||||||
|
# TF_VAR_k8s_allowed_remote_ips: '["0.0.0.0/0"]'
|
67
.gitlab-ci/vagrant.yml
Normal file
67
.gitlab-ci/vagrant.yml
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
.vagrant:
|
||||||
|
extends: .testcases
|
||||||
|
variables:
|
||||||
|
CI_PLATFORM: "vagrant"
|
||||||
|
SSH_USER: "vagrant"
|
||||||
|
VAGRANT_DEFAULT_PROVIDER: "libvirt"
|
||||||
|
KUBESPRAY_VAGRANT_CONFIG: tests/files/${CI_JOB_NAME}.rb
|
||||||
|
tags: [c3.small.x86]
|
||||||
|
only: [/^pr-.*$/]
|
||||||
|
except: ['triggers']
|
||||||
|
image: quay.io/kubespray/vagrant:$KUBESPRAY_VERSION
|
||||||
|
services: []
|
||||||
|
before_script:
|
||||||
|
- apt-get update && apt-get install -y python3-pip
|
||||||
|
- update-alternatives --install /usr/bin/python python /usr/bin/python3 10
|
||||||
|
- python -m pip uninstall -y ansible ansible-base ansible-core
|
||||||
|
- python -m pip install -r tests/requirements.txt
|
||||||
|
- ./tests/scripts/vagrant_clean.sh
|
||||||
|
script:
|
||||||
|
- ./tests/scripts/testcases_run.sh
|
||||||
|
after_script:
|
||||||
|
- chronic ./tests/scripts/testcases_cleanup.sh
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
|
vagrant_ubuntu18-calico-dual-stack:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .vagrant
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
vagrant_ubuntu18-flannel:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .vagrant
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
vagrant_ubuntu18-weave-medium:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .vagrant
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
vagrant_ubuntu20-flannel:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .vagrant
|
||||||
|
when: on_success
|
||||||
|
allow_failure: false
|
||||||
|
|
||||||
|
vagrant_ubuntu16-kube-router-sep:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .vagrant
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
# Service proxy test fails connectivity testing
|
||||||
|
vagrant_ubuntu16-kube-router-svc-proxy:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .vagrant
|
||||||
|
when: manual
|
||||||
|
|
||||||
|
vagrant_fedora35-kube-router:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .vagrant
|
||||||
|
when: on_success
|
||||||
|
|
||||||
|
vagrant_centos7-kube-router:
|
||||||
|
stage: deploy-part2
|
||||||
|
extends: .vagrant
|
||||||
|
when: manual
|
3
.markdownlint.yaml
Normal file
3
.markdownlint.yaml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
MD013: false
|
||||||
|
MD029: false
|
48
.pre-commit-config.yaml
Normal file
48
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/adrienverge/yamllint.git
|
||||||
|
rev: v1.27.1
|
||||||
|
hooks:
|
||||||
|
- id: yamllint
|
||||||
|
args: [--strict]
|
||||||
|
|
||||||
|
- repo: https://github.com/markdownlint/markdownlint
|
||||||
|
rev: v0.11.0
|
||||||
|
hooks:
|
||||||
|
- id: markdownlint
|
||||||
|
args: [ -r, "~MD013,~MD029" ]
|
||||||
|
exclude: "^.git"
|
||||||
|
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: ansible-lint
|
||||||
|
name: ansible-lint
|
||||||
|
entry: ansible-lint -v
|
||||||
|
language: python
|
||||||
|
pass_filenames: false
|
||||||
|
additional_dependencies:
|
||||||
|
- .[community]
|
||||||
|
|
||||||
|
- id: ansible-syntax-check
|
||||||
|
name: ansible-syntax-check
|
||||||
|
entry: env ANSIBLE_INVENTORY=inventory/local-tests.cfg ANSIBLE_REMOTE_USER=root ANSIBLE_BECOME="true" ANSIBLE_BECOME_USER=root ANSIBLE_VERBOSITY="3" ansible-playbook --syntax-check
|
||||||
|
language: python
|
||||||
|
files: "^cluster.yml|^upgrade-cluster.yml|^reset.yml|^extra_playbooks/upgrade-only-k8s.yml"
|
||||||
|
|
||||||
|
- id: tox-inventory-builder
|
||||||
|
name: tox-inventory-builder
|
||||||
|
entry: bash -c "cd contrib/inventory_builder && tox"
|
||||||
|
language: python
|
||||||
|
pass_filenames: false
|
||||||
|
|
||||||
|
- id: check-readme-versions
|
||||||
|
name: check-readme-versions
|
||||||
|
entry: tests/scripts/check_readme_versions.sh
|
||||||
|
language: script
|
||||||
|
pass_filenames: false
|
||||||
|
|
||||||
|
- id: ci-matrix
|
||||||
|
name: ci-matrix
|
||||||
|
entry: tests/scripts/md-table/test.sh
|
||||||
|
language: script
|
||||||
|
pass_filenames: false
|
149
.travis.yml
149
.travis.yml
|
@ -1,149 +0,0 @@
|
||||||
sudo: false
|
|
||||||
|
|
||||||
git:
|
|
||||||
depth: 5
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
GCE_USER=travis
|
|
||||||
SSH_USER=$GCE_USER
|
|
||||||
TEST_ID=$TRAVIS_JOB_NUMBER
|
|
||||||
CONTAINER_ENGINE=docker
|
|
||||||
PRIVATE_KEY=$GCE_PRIVATE_KEY
|
|
||||||
ANSIBLE_KEEP_REMOTE_FILES=1
|
|
||||||
matrix:
|
|
||||||
# Debian Jessie
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=flannel
|
|
||||||
CLOUD_IMAGE=debian-8-kubespray
|
|
||||||
CLOUD_REGION=europe-west1-b
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=calico
|
|
||||||
CLOUD_IMAGE=debian-8-kubespray
|
|
||||||
CLOUD_REGION=us-central1-c
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=weave
|
|
||||||
CLOUD_IMAGE=debian-8-kubespray
|
|
||||||
CLOUD_REGION=us-east1-d
|
|
||||||
|
|
||||||
# Centos 7
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=flannel
|
|
||||||
CLOUD_IMAGE=centos-7-sudo
|
|
||||||
CLOUD_REGION=asia-east1-c
|
|
||||||
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=calico
|
|
||||||
CLOUD_IMAGE=centos-7-sudo
|
|
||||||
CLOUD_REGION=europe-west1-b
|
|
||||||
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=weave
|
|
||||||
CLOUD_IMAGE=centos-7-sudo
|
|
||||||
CLOUD_REGION=us-central1-c
|
|
||||||
|
|
||||||
# Redhat 7
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=flannel
|
|
||||||
CLOUD_IMAGE=rhel-7-sudo
|
|
||||||
CLOUD_REGION=us-east1-d
|
|
||||||
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=calico
|
|
||||||
CLOUD_IMAGE=rhel-7-sudo
|
|
||||||
CLOUD_REGION=asia-east1-c
|
|
||||||
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=weave
|
|
||||||
CLOUD_IMAGE=rhel-7-sudo
|
|
||||||
CLOUD_REGION=europe-west1-b
|
|
||||||
|
|
||||||
# Ubuntu 16.04
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=flannel
|
|
||||||
CLOUD_IMAGE=ubuntu-1604-xenial
|
|
||||||
CLOUD_REGION=us-central1-c
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=calico
|
|
||||||
CLOUD_IMAGE=ubuntu-1604-xenial
|
|
||||||
CLOUD_REGION=us-east1-d
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=weave
|
|
||||||
CLOUD_IMAGE=ubuntu-1604-xenial
|
|
||||||
CLOUD_REGION=asia-east1-c
|
|
||||||
|
|
||||||
# Ubuntu 15.10
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=flannel
|
|
||||||
CLOUD_IMAGE=ubuntu-1510-wily
|
|
||||||
CLOUD_REGION=europe-west1-b
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=calico
|
|
||||||
CLOUD_IMAGE=ubuntu-1510-wily
|
|
||||||
CLOUD_REGION=us-central1-a
|
|
||||||
- >-
|
|
||||||
KUBE_NETWORK_PLUGIN=weave
|
|
||||||
CLOUD_IMAGE=ubuntu-1510-wily
|
|
||||||
CLOUD_REGION=us-east1-d
|
|
||||||
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
# Install Ansible.
|
|
||||||
- pip install --user boto -U
|
|
||||||
- pip install --user ansible
|
|
||||||
- pip install --user netaddr
|
|
||||||
- pip install --user apache-libcloud
|
|
||||||
|
|
||||||
cache:
|
|
||||||
- directories:
|
|
||||||
- $HOME/.cache/pip
|
|
||||||
- $HOME/.local
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- echo "RUN $TRAVIS_JOB_NUMBER $KUBE_NETWORK_PLUGIN $CONTAINER_ENGINE "
|
|
||||||
- mkdir -p $HOME/.ssh
|
|
||||||
- echo $PRIVATE_KEY | base64 -d > $HOME/.ssh/id_rsa
|
|
||||||
- echo $GCE_PEM_FILE | base64 -d > $HOME/.ssh/gce
|
|
||||||
- chmod 400 $HOME/.ssh/id_rsa
|
|
||||||
- chmod 755 $HOME/.local/bin/ansible-playbook
|
|
||||||
- $HOME/.local/bin/ansible-playbook --version
|
|
||||||
- cp tests/ansible.cfg .
|
|
||||||
# - "echo $HOME/.local/bin/ansible-playbook -i inventory.ini -u $SSH_USER -e ansible_ssh_user=$SSH_USER $SSH_ARGS -b --become-user=root -e '{\"cloud_provider\": true}' $LOG_LEVEL -e kube_network_plugin=${KUBE_NETWORK_PLUGIN} setup-kubernetes/cluster.yml"
|
|
||||||
## Configure ansible deployment logs to be collected as an artifact. Enable when GCS configured, see https://docs.travis-ci.com/user/deployment/gcs
|
|
||||||
# - $HOME/.local/bin/ansible-playbook -u $SSH_USER -e ansible_ssh_user=$SSH_USER $SSH_ARGS -b --become-user=root scritps/configure-logs.yaml
|
|
||||||
|
|
||||||
script:
|
|
||||||
- >
|
|
||||||
$HOME/.local/bin/ansible-playbook tests/cloud_playbooks/create-gce.yml -i tests/local_inventory/hosts -c local $LOG_LEVEL
|
|
||||||
-e test_id=${TEST_ID}
|
|
||||||
-e kube_network_plugin=${KUBE_NETWORK_PLUGIN}
|
|
||||||
-e gce_project_id=${GCE_PROJECT_ID}
|
|
||||||
-e gce_service_account_email=${GCE_ACCOUNT}
|
|
||||||
-e gce_pem_file=${HOME}/.ssh/gce
|
|
||||||
-e cloud_image=${CLOUD_IMAGE}
|
|
||||||
-e inventory_path=${PWD}/inventory/inventory.ini
|
|
||||||
-e cloud_region=${CLOUD_REGION}
|
|
||||||
|
|
||||||
# Create cluster
|
|
||||||
- "$HOME/.local/bin/ansible-playbook -i inventory/inventory.ini -u $SSH_USER -e ansible_ssh_user=$SSH_USER $SSH_ARGS -b --become-user=root -e cloud_provider=gce $LOG_LEVEL -e kube_network_plugin=${KUBE_NETWORK_PLUGIN} cluster.yml"
|
|
||||||
# Tests Cases
|
|
||||||
## Test Master API
|
|
||||||
- $HOME/.local/bin/ansible-playbook -i inventory/inventory.ini tests/testcases/010_check-apiserver.yml $LOG_LEVEL
|
|
||||||
## Create a POD
|
|
||||||
- $HOME/.local/bin/ansible-playbook -i inventory/inventory.ini -u $SSH_USER -e ansible_ssh_user=$SSH_USER $SSH_ARGS -b --become-user=root tests/testcases/020_check-create-pod.yml $LOG_LEVEL
|
|
||||||
## Ping the between 2 pod
|
|
||||||
- $HOME/.local/bin/ansible-playbook -i inventory/inventory.ini -u $SSH_USER -e ansible_ssh_user=$SSH_USER $SSH_ARGS -b --become-user=root tests/testcases/030_check-network.yml $LOG_LEVEL
|
|
||||||
## Collect env info, enable it once GCS configured, see https://docs.travis-ci.com/user/deployment/gcs
|
|
||||||
# - $HOME/.local/bin/ansible-playbook -i inventory/inventory.ini -u $SSH_USER -e ansible_ssh_user=$SSH_USER $SSH_ARGS -b --become-user=root scritps/collect-info.yaml
|
|
||||||
|
|
||||||
after_script:
|
|
||||||
- >
|
|
||||||
$HOME/.local/bin/ansible-playbook -i inventory/inventory.ini tests/cloud_playbooks/delete-gce.yml -c local $LOG_LEVEL
|
|
||||||
-e test_id=${TEST_ID}
|
|
||||||
-e kube_network_plugin=${KUBE_NETWORK_PLUGIN}
|
|
||||||
-e gce_project_id=${GCE_PROJECT_ID}
|
|
||||||
-e gce_service_account_email=${GCE_ACCOUNT}
|
|
||||||
-e gce_pem_file=${HOME}/.ssh/gce
|
|
||||||
-e cloud_image=${CLOUD_IMAGE}
|
|
||||||
-e inventory_path=${PWD}/inventory/inventory.ini
|
|
||||||
-e cloud_region=${CLOUD_REGION}
|
|
19
.yamllint
Normal file
19
.yamllint
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
extends: default
|
||||||
|
|
||||||
|
ignore: |
|
||||||
|
.git/
|
||||||
|
|
||||||
|
rules:
|
||||||
|
braces:
|
||||||
|
min-spaces-inside: 0
|
||||||
|
max-spaces-inside: 1
|
||||||
|
brackets:
|
||||||
|
min-spaces-inside: 0
|
||||||
|
max-spaces-inside: 1
|
||||||
|
indentation:
|
||||||
|
spaces: 2
|
||||||
|
indent-sequences: consistent
|
||||||
|
line-length: disable
|
||||||
|
new-line-at-end-of-file: disable
|
||||||
|
truthy: disable
|
1
CNAME
Normal file
1
CNAME
Normal file
|
@ -0,0 +1 @@
|
||||||
|
kubespray.io
|
|
@ -2,9 +2,45 @@
|
||||||
|
|
||||||
## How to become a contributor and submit your own code
|
## How to become a contributor and submit your own code
|
||||||
|
|
||||||
|
### Environment setup
|
||||||
|
|
||||||
|
It is recommended to use filter to manage the GitHub email notification, see [examples for setting filters to Kubernetes Github notifications](https://github.com/kubernetes/community/blob/master/communication/best-practices.md#examples-for-setting-filters-to-kubernetes-github-notifications)
|
||||||
|
|
||||||
|
To install development dependencies you can set up a python virtual env with the necessary dependencies:
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
virtualenv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install -r tests/requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Linting
|
||||||
|
|
||||||
|
Kubespray uses [pre-commit](https://pre-commit.com) hook configuration to run several linters, please install this tool and use it to run validation tests before submitting a PR.
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
pre-commit install
|
||||||
|
pre-commit run -a # To run pre-commit hook on all files in the repository, even if they were not modified
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Molecule
|
||||||
|
|
||||||
|
[molecule](https://github.com/ansible-community/molecule) is designed to help the development and testing of Ansible roles. In Kubespray you can run it all for all roles with `./tests/scripts/molecule_run.sh` or for a specific role (that you are working with) with `molecule test` from the role directory (`cd roles/my-role`).
|
||||||
|
|
||||||
|
When developing or debugging a role it can be useful to run `molecule create` and `molecule converge` separately. Then you can use `molecule login` to SSH into the test environment.
|
||||||
|
|
||||||
|
#### Vagrant
|
||||||
|
|
||||||
|
Vagrant with VirtualBox or libvirt driver helps you to quickly spin test clusters to test things end to end. See [README.md#vagrant](README.md)
|
||||||
|
|
||||||
### Contributing A Patch
|
### Contributing A Patch
|
||||||
|
|
||||||
1. Submit an issue describing your proposed change to the repo in question.
|
1. Submit an issue describing your proposed change to the repo in question.
|
||||||
2. The [repo owners](OWNERS) will respond to your issue promptly.
|
2. The [repo owners](OWNERS) will respond to your issue promptly.
|
||||||
3. Fork the desired repo, develop and test your code changes.
|
3. Fork the desired repo, develop and test your code changes.
|
||||||
4. Submit a pull request.
|
4. Install [pre-commit](https://pre-commit.com) and install it in your development repo.
|
||||||
|
5. Addess any pre-commit validation failures.
|
||||||
|
6. Sign the CNCF CLA (<https://git.k8s.io/community/CLA.md#the-contributor-license-agreement>)
|
||||||
|
7. Submit a pull request.
|
||||||
|
8. Work with the reviewers on their suggestions.
|
||||||
|
9. Ensure to rebase to the HEAD of your target branch and squash un-necessary commits (<https://blog.carbonfive.com/always-squash-and-rebase-your-git-commits/>) before final merger of your contribution.
|
||||||
|
|
37
Dockerfile
Normal file
37
Dockerfile
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# Use imutable image tags rather than mutable tags (like ubuntu:20.04)
|
||||||
|
FROM ubuntu:focal-20220531
|
||||||
|
|
||||||
|
ARG ARCH=amd64
|
||||||
|
ARG TZ=Etc/UTC
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
|
RUN apt update -y \
|
||||||
|
&& apt install -y \
|
||||||
|
libssl-dev python3-dev sshpass apt-transport-https jq moreutils \
|
||||||
|
ca-certificates curl gnupg2 software-properties-common python3-pip unzip rsync git \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - \
|
||||||
|
&& add-apt-repository \
|
||||||
|
"deb [arch=$ARCH] https://download.docker.com/linux/ubuntu \
|
||||||
|
$(lsb_release -cs) \
|
||||||
|
stable" \
|
||||||
|
&& apt update -y && apt-get install --no-install-recommends -y docker-ce \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Some tools like yamllint need this
|
||||||
|
# Pip needs this as well at the moment to install ansible
|
||||||
|
# (and potentially other packages)
|
||||||
|
# See: https://github.com/pypa/pip/issues/10219
|
||||||
|
ENV LANG=C.UTF-8
|
||||||
|
|
||||||
|
WORKDIR /kubespray
|
||||||
|
COPY . .
|
||||||
|
RUN /usr/bin/python3 -m pip install --no-cache-dir pip -U \
|
||||||
|
&& /usr/bin/python3 -m pip install --no-cache-dir -r tests/requirements.txt \
|
||||||
|
&& python3 -m pip install --no-cache-dir -r requirements.txt \
|
||||||
|
&& update-alternatives --install /usr/bin/python python /usr/bin/python3 1
|
||||||
|
|
||||||
|
RUN KUBE_VERSION=$(sed -n 's/^kube_version: //p' roles/kubespray-defaults/defaults/main.yaml) \
|
||||||
|
&& curl -LO https://storage.googleapis.com/kubernetes-release/release/$KUBE_VERSION/bin/linux/$ARCH/kubectl \
|
||||||
|
&& chmod a+x kubectl \
|
||||||
|
&& mv kubectl /usr/local/bin/kubectl
|
7
Makefile
Normal file
7
Makefile
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
mitogen:
|
||||||
|
@echo Mitogen support is deprecated.
|
||||||
|
@echo Please run the following command manually:
|
||||||
|
@echo ansible-playbook -c local mitogen.yml -vv
|
||||||
|
clean:
|
||||||
|
rm -rf dist/
|
||||||
|
rm *.retry
|
12
OWNERS
12
OWNERS
|
@ -1,6 +1,8 @@
|
||||||
# See the OWNERS file documentation:
|
# See the OWNERS docs at https://go.k8s.io/owners
|
||||||
# https://github.com/kubernetes/kubernetes/blob/master/docs/devel/owners.md
|
|
||||||
|
|
||||||
owners:
|
approvers:
|
||||||
- Smana
|
- kubespray-approvers
|
||||||
- ant31
|
reviewers:
|
||||||
|
- kubespray-reviewers
|
||||||
|
emeritus_approvers:
|
||||||
|
- kubespray-emeritus_approvers
|
26
OWNERS_ALIASES
Normal file
26
OWNERS_ALIASES
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
aliases:
|
||||||
|
kubespray-approvers:
|
||||||
|
- mattymo
|
||||||
|
- chadswen
|
||||||
|
- mirwan
|
||||||
|
- miouge1
|
||||||
|
- luckysb
|
||||||
|
- floryut
|
||||||
|
- oomichi
|
||||||
|
- cristicalin
|
||||||
|
- liupeng0518
|
||||||
|
- yankay
|
||||||
|
kubespray-reviewers:
|
||||||
|
- holmsten
|
||||||
|
- bozzo
|
||||||
|
- eppo
|
||||||
|
- oomichi
|
||||||
|
- jayonlau
|
||||||
|
- cristicalin
|
||||||
|
- liupeng0518
|
||||||
|
- yankay
|
||||||
|
kubespray-emeritus_approvers:
|
||||||
|
- riverzhang
|
||||||
|
- atoms
|
||||||
|
- ant31
|
||||||
|
- woopstar
|
288
README.md
288
README.md
|
@ -1,87 +1,261 @@
|
||||||
![Kubespray Logo](http://s9.postimg.org/md5dyjl67/kubespray_logoandkubespray_small.png)
|
# Deploy a Production Ready Kubernetes Cluster
|
||||||
|
|
||||||
##Deploy a production ready kubernetes cluster
|
![Kubernetes Logo](https://raw.githubusercontent.com/kubernetes-sigs/kubespray/master/docs/img/kubernetes-logo.png)
|
||||||
|
|
||||||
If you have questions, you can [invite yourself](https://slack.kubespray.io/) to **chat** with us on Slack! [![SlackStatus](https://slack.kubespray.io/badge.svg)](https://kubespray.slack.com)
|
If you have questions, check the documentation at [kubespray.io](https://kubespray.io) and join us on the [kubernetes slack](https://kubernetes.slack.com), channel **\#kubespray**.
|
||||||
|
You can get your invite [here](http://slack.k8s.io/)
|
||||||
|
|
||||||
- Can be deployed on **AWS, GCE, OpenStack or Baremetal**
|
- Can be deployed on **[AWS](docs/aws.md), GCE, [Azure](docs/azure.md), [OpenStack](docs/openstack.md), [vSphere](docs/vsphere.md), [Equinix Metal](docs/equinix-metal.md) (bare metal), Oracle Cloud Infrastructure (Experimental), or Baremetal**
|
||||||
- **High available** cluster
|
- **Highly available** cluster
|
||||||
- **Composable** (Choice of the network plugin for instance)
|
- **Composable** (Choice of the network plugin for instance)
|
||||||
- Support most popular **Linux distributions**
|
- Supports most popular **Linux distributions**
|
||||||
- **Continuous integration tests**
|
- **Continuous integration tests**
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
To deploy the cluster you can use :
|
To deploy the cluster you can use :
|
||||||
|
|
||||||
[**kargo-cli**](https://github.com/kubespray/kargo-cli) (deprecated, a newer [go](https://github.com/Smana/kargo-cli/tree/kargogo) version soon)<br>
|
### Ansible
|
||||||
**Ansible** usual commands <br>
|
|
||||||
**vagrant** by simply running `vagrant up` (for tests purposes) <br>
|
|
||||||
|
|
||||||
|
#### Usage
|
||||||
|
|
||||||
* [Requirements](#requirements)
|
Install Ansible according to [Ansible installation guide](/docs/ansible.md#installing-ansible)
|
||||||
* [Getting started](docs/getting-started.md)
|
then run the following steps:
|
||||||
* [Vagrant install](docs/vagrant.md)
|
|
||||||
* [CoreOS bootstrap](docs/coreos.md)
|
|
||||||
* [Ansible variables](docs/ansible.md)
|
|
||||||
* [Cloud providers](docs/cloud.md)
|
|
||||||
* [OpenStack](docs/openstack.md)
|
|
||||||
* [AWS](docs/aws.md)
|
|
||||||
* [Network plugins](#network-plugins)
|
|
||||||
* [Roadmap](docs/roadmap.md)
|
|
||||||
|
|
||||||
Supported Linux distributions
|
```ShellSession
|
||||||
===============
|
# Copy ``inventory/sample`` as ``inventory/mycluster``
|
||||||
|
cp -rfp inventory/sample inventory/mycluster
|
||||||
|
|
||||||
* **CoreOS**
|
# Update Ansible inventory file with inventory builder
|
||||||
* **Debian** Wheezy, Jessie
|
declare -a IPS=(10.10.1.3 10.10.1.4 10.10.1.5)
|
||||||
* **Ubuntu** 14.10, 15.04, 15.10, 16.04
|
CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
|
||||||
* **Fedora** 23
|
|
||||||
* **CentOS/RHEL** 7
|
|
||||||
|
|
||||||
Versions
|
# Review and change parameters under ``inventory/mycluster/group_vars``
|
||||||
--------------
|
cat inventory/mycluster/group_vars/all/all.yml
|
||||||
|
cat inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
|
||||||
|
|
||||||
[kubernetes](https://github.com/kubernetes/kubernetes/releases) v1.4.0 <br>
|
# Deploy Kubespray with Ansible Playbook - run the playbook as root
|
||||||
[etcd](https://github.com/coreos/etcd/releases) v3.0.1 <br>
|
# The option `--become` is required, as for example writing SSL keys in /etc/,
|
||||||
[calicoctl](https://github.com/projectcalico/calico-docker/releases) v0.20.0 <br>
|
# installing packages and interacting with various systemd daemons.
|
||||||
[flanneld](https://github.com/coreos/flannel/releases) v0.5.5 <br>
|
# Without --become the playbook will fail to run!
|
||||||
[weave](http://weave.works/) v1.6.1 <br>
|
ansible-playbook -i inventory/mycluster/hosts.yaml --become --become-user=root cluster.yml
|
||||||
[docker](https://www.docker.com/) v1.10.3 <br>
|
```
|
||||||
|
|
||||||
|
Note: When Ansible is already installed via system packages on the control machine, other python packages installed via `sudo pip install -r requirements.txt` will go to a different directory tree (e.g. `/usr/local/lib/python2.7/dist-packages` on Ubuntu) from Ansible's (e.g. `/usr/lib/python2.7/dist-packages/ansible` still on Ubuntu).
|
||||||
|
As a consequence, `ansible-playbook` command will fail with:
|
||||||
|
|
||||||
Requirements
|
```raw
|
||||||
--------------
|
ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
|
||||||
|
```
|
||||||
|
|
||||||
* The target servers must have **access to the Internet** in order to pull docker images.
|
probably pointing on a task depending on a module present in requirements.txt.
|
||||||
* The **firewalls are not managed**, you'll need to implement your own rules the way you used to.
|
|
||||||
in order to avoid any issue during deployment you should disable your firewall
|
|
||||||
* **Copy your ssh keys** to all the servers part of your inventory.
|
|
||||||
* **Ansible v2.x and python-netaddr**
|
|
||||||
|
|
||||||
|
One way of solving this would be to uninstall the Ansible package and then, to install it via pip but it is not always possible.
|
||||||
|
A workaround consists of setting `ANSIBLE_LIBRARY` and `ANSIBLE_MODULE_UTILS` environment variables respectively to the `ansible/modules` and `ansible/module_utils` subdirectories of pip packages installation location, which can be found in the Location field of the output of `pip show [package]` before executing `ansible-playbook`.
|
||||||
|
|
||||||
## Network plugins
|
A simple way to ensure you get all the correct version of Ansible is to use the [pre-built docker image from Quay](https://quay.io/repository/kubespray/kubespray?tab=tags).
|
||||||
You can choose between 3 network plugins. (default: `flannel` with vxlan backend)
|
You will then need to use [bind mounts](https://docs.docker.com/storage/bind-mounts/) to get the inventory and ssh key into the container, like this:
|
||||||
|
|
||||||
* [**flannel**](docs/flannel.md): gre/vxlan (layer 2) networking.
|
```ShellSession
|
||||||
|
git checkout v2.20.0
|
||||||
|
docker pull quay.io/kubespray/kubespray:v2.20.0
|
||||||
|
docker run --rm -it --mount type=bind,source="$(pwd)"/inventory/sample,dst=/inventory \
|
||||||
|
--mount type=bind,source="${HOME}"/.ssh/id_rsa,dst=/root/.ssh/id_rsa \
|
||||||
|
quay.io/kubespray/kubespray:v2.20.0 bash
|
||||||
|
# Inside the container you may now run the kubespray playbooks:
|
||||||
|
ansible-playbook -i /inventory/inventory.ini --private-key /root/.ssh/id_rsa cluster.yml
|
||||||
|
```
|
||||||
|
|
||||||
* [**calico**](docs/calico.md): bgp (layer 3) networking.
|
### Vagrant
|
||||||
|
|
||||||
* **weave**: Weave is a lightweight container overlay network that doesn't require an external K/V database cluster. <br>
|
For Vagrant we need to install python dependencies for provisioning tasks.
|
||||||
(Please refer to `weave` [troubleshooting documentation](http://docs.weave.works/weave/latest_release/troubleshooting.html))
|
Check if Python and pip are installed:
|
||||||
|
|
||||||
The choice is defined with the variable `kube_network_plugin`
|
```ShellSession
|
||||||
|
python -V && pip -V
|
||||||
|
```
|
||||||
|
|
||||||
|
If this returns the version of the software, you're good to go. If not, download and install Python from here <https://www.python.org/downloads/source/>
|
||||||
|
|
||||||
|
Install Ansible according to [Ansible installation guide](/docs/ansible.md#installing-ansible)
|
||||||
|
then run the following step:
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
vagrant up
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documents
|
||||||
|
|
||||||
|
- [Requirements](#requirements)
|
||||||
|
- [Kubespray vs ...](docs/comparisons.md)
|
||||||
|
- [Getting started](docs/getting-started.md)
|
||||||
|
- [Setting up your first cluster](docs/setting-up-your-first-cluster.md)
|
||||||
|
- [Ansible inventory and tags](docs/ansible.md)
|
||||||
|
- [Integration with existing ansible repo](docs/integration.md)
|
||||||
|
- [Deployment data variables](docs/vars.md)
|
||||||
|
- [DNS stack](docs/dns-stack.md)
|
||||||
|
- [HA mode](docs/ha-mode.md)
|
||||||
|
- [Network plugins](#network-plugins)
|
||||||
|
- [Vagrant install](docs/vagrant.md)
|
||||||
|
- [Flatcar Container Linux bootstrap](docs/flatcar.md)
|
||||||
|
- [Fedora CoreOS bootstrap](docs/fcos.md)
|
||||||
|
- [Debian Jessie setup](docs/debian.md)
|
||||||
|
- [openSUSE setup](docs/opensuse.md)
|
||||||
|
- [Downloaded artifacts](docs/downloads.md)
|
||||||
|
- [Cloud providers](docs/cloud.md)
|
||||||
|
- [OpenStack](docs/openstack.md)
|
||||||
|
- [AWS](docs/aws.md)
|
||||||
|
- [Azure](docs/azure.md)
|
||||||
|
- [vSphere](docs/vsphere.md)
|
||||||
|
- [Equinix Metal](docs/equinix-metal.md)
|
||||||
|
- [Large deployments](docs/large-deployments.md)
|
||||||
|
- [Adding/replacing a node](docs/nodes.md)
|
||||||
|
- [Upgrades basics](docs/upgrades.md)
|
||||||
|
- [Air-Gap installation](docs/offline-environment.md)
|
||||||
|
- [NTP](docs/ntp.md)
|
||||||
|
- [Hardening](docs/hardening.md)
|
||||||
|
- [Mirror](docs/mirror.md)
|
||||||
|
- [Roadmap](docs/roadmap.md)
|
||||||
|
|
||||||
|
## Supported Linux Distributions
|
||||||
|
|
||||||
|
- **Flatcar Container Linux by Kinvolk**
|
||||||
|
- **Debian** Bullseye, Buster, Jessie, Stretch
|
||||||
|
- **Ubuntu** 16.04, 18.04, 20.04, 22.04
|
||||||
|
- **CentOS/RHEL** 7, [8, 9](docs/centos.md#centos-8)
|
||||||
|
- **Fedora** 35, 36
|
||||||
|
- **Fedora CoreOS** (see [fcos Note](docs/fcos.md))
|
||||||
|
- **openSUSE** Leap 15.x/Tumbleweed
|
||||||
|
- **Oracle Linux** 7, [8, 9](docs/centos.md#centos-8)
|
||||||
|
- **Alma Linux** [8, 9](docs/centos.md#centos-8)
|
||||||
|
- **Rocky Linux** [8, 9](docs/centos.md#centos-8)
|
||||||
|
- **Kylin Linux Advanced Server V10** (experimental: see [kylin linux notes](docs/kylinlinux.md))
|
||||||
|
- **Amazon Linux 2** (experimental: see [amazon linux notes](docs/amazonlinux.md))
|
||||||
|
- **UOS Linux** (experimental: see [uos linux notes](docs/uoslinux.md))
|
||||||
|
- **openEuler** (experimental: see [openEuler notes](docs/openeuler.md))
|
||||||
|
|
||||||
|
Note: Upstart/SysV init based OS types are not supported.
|
||||||
|
|
||||||
|
## Supported Components
|
||||||
|
|
||||||
|
- Core
|
||||||
|
- [kubernetes](https://github.com/kubernetes/kubernetes) v1.25.5
|
||||||
|
- [etcd](https://github.com/etcd-io/etcd) v3.5.6
|
||||||
|
- [docker](https://www.docker.com/) v20.10 (see note)
|
||||||
|
- [containerd](https://containerd.io/) v1.6.14
|
||||||
|
- [cri-o](http://cri-o.io/) v1.24 (experimental: see [CRI-O Note](docs/cri-o.md). Only on fedora, ubuntu and centos based OS)
|
||||||
|
- Network Plugin
|
||||||
|
- [cni-plugins](https://github.com/containernetworking/plugins) v1.1.1
|
||||||
|
- [calico](https://github.com/projectcalico/calico) v3.24.5
|
||||||
|
- [canal](https://github.com/projectcalico/canal) (given calico/flannel versions)
|
||||||
|
- [cilium](https://github.com/cilium/cilium) v1.12.1
|
||||||
|
- [flannel](https://github.com/flannel-io/flannel) v0.19.2
|
||||||
|
- [kube-ovn](https://github.com/alauda/kube-ovn) v1.10.7
|
||||||
|
- [kube-router](https://github.com/cloudnativelabs/kube-router) v1.5.1
|
||||||
|
- [multus](https://github.com/intel/multus-cni) v3.8
|
||||||
|
- [weave](https://github.com/weaveworks/weave) v2.8.1
|
||||||
|
- [kube-vip](https://github.com/kube-vip/kube-vip) v0.5.5
|
||||||
|
- Application
|
||||||
|
- [cert-manager](https://github.com/jetstack/cert-manager) v1.10.1
|
||||||
|
- [coredns](https://github.com/coredns/coredns) v1.9.3
|
||||||
|
- [ingress-nginx](https://github.com/kubernetes/ingress-nginx) v1.5.1
|
||||||
|
- [krew](https://github.com/kubernetes-sigs/krew) v0.4.3
|
||||||
|
- [argocd](https://argoproj.github.io/) v2.4.16
|
||||||
|
- [helm](https://helm.sh/) v3.9.4
|
||||||
|
- [metallb](https://metallb.universe.tf/) v0.12.1
|
||||||
|
- [registry](https://github.com/distribution/distribution) v2.8.1
|
||||||
|
- Storage Plugin
|
||||||
|
- [cephfs-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.0-k8s1.11
|
||||||
|
- [rbd-provisioner](https://github.com/kubernetes-incubator/external-storage) v2.1.1-k8s1.11
|
||||||
|
- [aws-ebs-csi-plugin](https://github.com/kubernetes-sigs/aws-ebs-csi-driver) v0.5.0
|
||||||
|
- [azure-csi-plugin](https://github.com/kubernetes-sigs/azuredisk-csi-driver) v1.10.0
|
||||||
|
- [cinder-csi-plugin](https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/cinder-csi-plugin/using-cinder-csi-plugin.md) v1.22.0
|
||||||
|
- [gcp-pd-csi-plugin](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver) v1.4.0
|
||||||
|
- [local-path-provisioner](https://github.com/rancher/local-path-provisioner) v0.0.22
|
||||||
|
- [local-volume-provisioner](https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner) v2.5.0
|
||||||
|
|
||||||
|
## Container Runtime Notes
|
||||||
|
|
||||||
|
- The list of available docker version is 18.09, 19.03 and 20.10. The recommended docker version is 20.10. The kubelet might break on docker's non-standard version numbering (it no longer uses semantic versioning). To ensure auto-updates don't break your cluster look into e.g. yum versionlock plugin or apt pin).
|
||||||
|
- The cri-o version should be aligned with the respective kubernetes version (i.e. kube_version=1.20.x, crio_version=1.20)
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- **Minimum required version of Kubernetes is v1.23**
|
||||||
|
- **Ansible v2.11+, Jinja 2.11+ and python-netaddr is installed on the machine that will run Ansible commands**
|
||||||
|
- The target servers must have **access to the Internet** in order to pull docker images. Otherwise, additional configuration is required (See [Offline Environment](docs/offline-environment.md))
|
||||||
|
- The target servers are configured to allow **IPv4 forwarding**.
|
||||||
|
- If using IPv6 for pods and services, the target servers are configured to allow **IPv6 forwarding**.
|
||||||
|
- The **firewalls are not managed**, you'll need to implement your own rules the way you used to.
|
||||||
|
in order to avoid any issue during deployment you should disable your firewall.
|
||||||
|
- If kubespray is ran from non-root user account, correct privilege escalation method
|
||||||
|
should be configured in the target servers. Then the `ansible_become` flag
|
||||||
|
or command parameters `--become or -b` should be specified.
|
||||||
|
|
||||||
|
Hardware:
|
||||||
|
These limits are safe guarded by Kubespray. Actual requirements for your workload can differ. For a sizing guide go to the [Building Large Clusters](https://kubernetes.io/docs/setup/cluster-large/#size-of-master-and-master-components) guide.
|
||||||
|
|
||||||
|
- Master
|
||||||
|
- Memory: 1500 MB
|
||||||
|
- Node
|
||||||
|
- Memory: 1024 MB
|
||||||
|
|
||||||
|
## Network Plugins
|
||||||
|
|
||||||
|
You can choose between 10 network plugins. (default: `calico`, except Vagrant uses `flannel`)
|
||||||
|
|
||||||
|
- [flannel](docs/flannel.md): gre/vxlan (layer 2) networking.
|
||||||
|
|
||||||
|
- [Calico](https://docs.projectcalico.org/latest/introduction/) is a networking and network policy provider. Calico supports a flexible set of networking options
|
||||||
|
designed to give you the most efficient networking across a range of situations, including non-overlay
|
||||||
|
and overlay networks, with or without BGP. Calico uses the same engine to enforce network policy for hosts,
|
||||||
|
pods, and (if using Istio and Envoy) applications at the service mesh layer.
|
||||||
|
|
||||||
|
- [canal](https://github.com/projectcalico/canal): a composition of calico and flannel plugins.
|
||||||
|
|
||||||
|
- [cilium](http://docs.cilium.io/en/latest/): layer 3/4 networking (as well as layer 7 to protect and secure application protocols), supports dynamic insertion of BPF bytecode into the Linux kernel to implement security services, networking and visibility logic.
|
||||||
|
|
||||||
|
- [weave](docs/weave.md): Weave is a lightweight container overlay network that doesn't require an external K/V database cluster.
|
||||||
|
(Please refer to `weave` [troubleshooting documentation](https://www.weave.works/docs/net/latest/troubleshooting/)).
|
||||||
|
|
||||||
|
- [kube-ovn](docs/kube-ovn.md): Kube-OVN integrates the OVN-based Network Virtualization with Kubernetes. It offers an advanced Container Network Fabric for Enterprises.
|
||||||
|
|
||||||
|
- [kube-router](docs/kube-router.md): Kube-router is a L3 CNI for Kubernetes networking aiming to provide operational
|
||||||
|
simplicity and high performance: it uses IPVS to provide Kube Services Proxy (if setup to replace kube-proxy),
|
||||||
|
iptables for network policies, and BGP for ods L3 networking (with optionally BGP peering with out-of-cluster BGP peers).
|
||||||
|
It can also optionally advertise routes to Kubernetes cluster Pods CIDRs, ClusterIPs, ExternalIPs and LoadBalancerIPs.
|
||||||
|
|
||||||
|
- [macvlan](docs/macvlan.md): Macvlan is a Linux network driver. Pods have their own unique Mac and Ip address, connected directly the physical (layer 2) network.
|
||||||
|
|
||||||
|
- [multus](docs/multus.md): Multus is a meta CNI plugin that provides multiple network interface support to pods. For each interface Multus delegates CNI calls to secondary CNI plugins such as Calico, macvlan, etc.
|
||||||
|
|
||||||
|
The choice is defined with the variable `kube_network_plugin`. There is also an
|
||||||
|
option to leverage built-in cloud provider networking instead.
|
||||||
|
See also [Network checker](docs/netcheck.md).
|
||||||
|
|
||||||
|
## Ingress Plugins
|
||||||
|
|
||||||
|
- [nginx](https://kubernetes.github.io/ingress-nginx): the NGINX Ingress Controller.
|
||||||
|
|
||||||
|
- [metallb](docs/metallb.md): the MetalLB bare-metal service LoadBalancer provider.
|
||||||
|
|
||||||
|
## Community docs and resources
|
||||||
|
|
||||||
|
- [kubernetes.io/docs/setup/production-environment/tools/kubespray/](https://kubernetes.io/docs/setup/production-environment/tools/kubespray/)
|
||||||
|
- [kubespray, monitoring and logging](https://github.com/gregbkr/kubernetes-kargo-logging-monitoring) by @gregbkr
|
||||||
|
- [Deploy Kubernetes w/ Ansible & Terraform](https://rsmitty.github.io/Terraform-Ansible-Kubernetes/) by @rsmitty
|
||||||
|
- [Deploy a Kubernetes Cluster with Kubespray (video)](https://www.youtube.com/watch?v=CJ5G4GpqDy0)
|
||||||
|
|
||||||
|
## Tools and projects on top of Kubespray
|
||||||
|
|
||||||
|
- [Digital Rebar Provision](https://github.com/digitalrebar/provision/blob/v4/doc/integrations/ansible.rst)
|
||||||
|
- [Terraform Contrib](https://github.com/kubernetes-sigs/kubespray/tree/master/contrib/terraform)
|
||||||
|
- [Kubean](https://github.com/kubean-io/kubean)
|
||||||
|
|
||||||
## CI Tests
|
## CI Tests
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/kubespray/kargo.svg)](https://travis-ci.org/kubespray/kargo) </br>
|
[![Build graphs](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/badges/master/pipeline.svg)](https://gitlab.com/kargo-ci/kubernetes-sigs-kubespray/pipelines)
|
||||||
|
|
||||||
### Google Compute Engine
|
CI/end-to-end tests sponsored by: [CNCF](https://cncf.io), [Equinix Metal](https://metal.equinix.com/), [OVHcloud](https://www.ovhcloud.com/), [ELASTX](https://elastx.se/).
|
||||||
|
|
||||||
| Calico | Flannel | Weave |
|
See the [test matrix](docs/test_cases.md) for details.
|
||||||
------------- | ------------- | ------------- | ------------- |
|
|
||||||
Ubuntu Xenial |[![Build Status](https://ci.kubespray.io/job/kargo-gce-xenial-calico/badge/icon)](https://ci.kubespray.io/job/kargo-gce-xenial-calico/)|[![Build Status](https://ci.kubespray.io/job/kargo-gce-xenial-flannel/badge/icon)](https://ci.kubespray.io/job/kargo-gce-xenial-flannel/)|[![Build Status](https://ci.kubespray.io/job/kargo-gce-xenial-weave/badge/icon)](https://ci.kubespray.io/job/kargo-gce-xenial-weave)|
|
|
||||||
CentOS 7 |[![Build Status](https://ci.kubespray.io/job/kargo-gce-centos7-calico/badge/icon)](https://ci.kubespray.io/job/kargo-gce-centos7-calico/)|[![Build Status](https://ci.kubespray.io/job/kargo-gce-centos7-flannel/badge/icon)](https://ci.kubespray.io/job/kargo-gce-centos7-flannel/)|[![Build Status](https://ci.kubespray.io/job/kargo-gce-centos7-weave/badge/icon)](https://ci.kubespray.io/job/kargo-gce-centos7-weave/)|
|
|
||||||
CoreOS (stable) |[![Build Status](https://ci.kubespray.io/job/kargo-gce-coreos-calico/badge/icon)](https://ci.kubespray.io/job/kargo-gce-coreos-calico/)|[![Build Status](https://ci.kubespray.io/job/kargo-gce-coreos-flannel/badge/icon)](https://ci.kubespray.io/job/kargo-gce-coreos-flannel/)|[![Build Status](https://ci.kubespray.io/job/kargo-gce-coreos-weave/badge/icon)](https://ci.kubespray.io/job/kargo-gce-coreos-weave/)|
|
|
||||||
|
|
||||||
CI tests sponsored by Google (GCE), and [teuto.net](https://teuto.net/) for OpenStack.
|
|
||||||
|
|
86
RELEASE.md
86
RELEASE.md
|
@ -1,9 +1,83 @@
|
||||||
# Release Process
|
# Release Process
|
||||||
|
|
||||||
The Kargo Project is released on an as-needed basis. The process is as follows:
|
The Kubespray Project is released on an as-needed basis. The process is as follows:
|
||||||
|
|
||||||
1. An issue is proposing a new release with a changelog since the last release
|
1. An issue is proposing a new release with a changelog since the last release. Please see [a good sample issue](https://github.com/kubernetes-sigs/kubespray/issues/8325)
|
||||||
2. At least on of the [OWNERS](OWNERS) must LGTM this release
|
2. At least one of the [approvers](OWNERS_ALIASES) must approve this release
|
||||||
3. An OWNER runs `git tag -s $VERSION` and inserts the changelog and pushes the tag with `git push $VERSION`
|
3. The `kube_version_min_required` variable is set to `n-1`
|
||||||
4. The release issue is closed
|
4. Remove hashes for [EOL versions](https://github.com/kubernetes/website/blob/main/content/en/releases/patch-releases.md) of kubernetes from `*_checksums` variables.
|
||||||
5. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] kargo $VERSION is released`
|
5. Create the release note with [Kubernetes Release Notes Generator](https://github.com/kubernetes/release/blob/master/cmd/release-notes/README.md). See the following `Release note creation` section for the details.
|
||||||
|
6. An approver creates [new release in GitHub](https://github.com/kubernetes-sigs/kubespray/releases/new) using a version and tag name like `vX.Y.Z` and attaching the release notes
|
||||||
|
7. An approver creates a release branch in the form `release-X.Y`
|
||||||
|
8. The corresponding version of [quay.io/kubespray/kubespray:vX.Y.Z](https://quay.io/repository/kubespray/kubespray) and [quay.io/kubespray/vagrant:vX.Y.Z](https://quay.io/repository/kubespray/vagrant) container images are built and tagged. See the following `Container image creation` section for the details.
|
||||||
|
9. The `KUBESPRAY_VERSION` variable is updated in `.gitlab-ci.yml`
|
||||||
|
10. The release issue is closed
|
||||||
|
11. An announcement email is sent to `dev@kubernetes.io` with the subject `[ANNOUNCE] Kubespray $VERSION is released`
|
||||||
|
12. The topic of the #kubespray channel is updated with `vX.Y.Z is released! | ...`
|
||||||
|
|
||||||
|
## Major/minor releases and milestones
|
||||||
|
|
||||||
|
* For major releases (vX.Y) Kubespray maintains one branch (`release-X.Y`). Minor releases (vX.Y.Z) are available only as tags.
|
||||||
|
|
||||||
|
* Security patches and bugs might be backported.
|
||||||
|
|
||||||
|
* Fixes for major releases (vX.Y) and minor releases (vX.Y.Z) are delivered
|
||||||
|
via maintenance releases (vX.Y.Z) and assigned to the corresponding open
|
||||||
|
[GitHub milestone](https://github.com/kubernetes-sigs/kubespray/milestones).
|
||||||
|
That milestone remains open for the major/minor releases support lifetime,
|
||||||
|
which ends once the milestone is closed. Then only a next major or minor release
|
||||||
|
can be done.
|
||||||
|
|
||||||
|
* Kubespray major and minor releases are bound to the given `kube_version` major/minor
|
||||||
|
version numbers and other components' arbitrary versions, like etcd or network plugins.
|
||||||
|
Older or newer component versions are not supported and not tested for the given
|
||||||
|
release (even if included in the checksum variables, like `kubeadm_checksums`).
|
||||||
|
|
||||||
|
* There is no unstable releases and no APIs, thus Kubespray doesn't follow
|
||||||
|
[semver](https://semver.org/). Every version describes only a stable release.
|
||||||
|
Breaking changes, if any introduced by changed defaults or non-contrib ansible roles'
|
||||||
|
playbooks, shall be described in the release notes. Other breaking changes, if any in
|
||||||
|
the contributed addons or bound versions of Kubernetes and other components, are
|
||||||
|
considered out of Kubespray scope and are up to the components' teams to deal with and
|
||||||
|
document.
|
||||||
|
|
||||||
|
* Minor releases can change components' versions, but not the major `kube_version`.
|
||||||
|
Greater `kube_version` requires a new major or minor release. For example, if Kubespray v2.0.0
|
||||||
|
is bound to `kube_version: 1.4.x`, `calico_version: 0.22.0`, `etcd_version: v3.0.6`,
|
||||||
|
then Kubespray v2.1.0 may be bound to only minor changes to `kube_version`, like v1.5.1
|
||||||
|
and *any* changes to other components, like etcd v4, or calico 1.2.3.
|
||||||
|
And Kubespray v3.x.x shall be bound to `kube_version: 2.x.x` respectively.
|
||||||
|
|
||||||
|
## Release note creation
|
||||||
|
|
||||||
|
You can create a release note with:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
export GITHUB_TOKEN=<your-github-token>
|
||||||
|
export ORG=kubernetes-sigs
|
||||||
|
export REPO=kubespray
|
||||||
|
release-notes --start-sha <The start commit-id> --end-sha <The end commit-id> --dependencies=false --output=/tmp/kubespray-release-note --required-author=""
|
||||||
|
```
|
||||||
|
|
||||||
|
If the release note file(/tmp/kubespray-release-note) contains "### Uncategorized" pull requests, those pull requests don't have a valid kind label(`kind/feature`, etc.).
|
||||||
|
It is necessary to put a valid label on each pull request and run the above release-notes command again to get a better release note)
|
||||||
|
|
||||||
|
## Container image creation
|
||||||
|
|
||||||
|
The container image `quay.io/kubespray/kubespray:vX.Y.Z` can be created from Dockerfile of the kubespray root directory:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cd kubespray/
|
||||||
|
nerdctl build -t quay.io/kubespray/kubespray:vX.Y.Z .
|
||||||
|
nerdctl push quay.io/kubespray/kubespray:vX.Y.Z
|
||||||
|
```
|
||||||
|
|
||||||
|
The container image `quay.io/kubespray/vagrant:vX.Y.Z` can be created from build.sh of test-infra/vagrant-docker/:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cd kubespray/test-infra/vagrant-docker/
|
||||||
|
./build vX.Y.Z
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that the above operation requires the permission to push container images into quay.io/kubespray/.
|
||||||
|
If you don't have the permission, please ask it on the #kubespray-dev channel.
|
||||||
|
|
15
SECURITY_CONTACTS
Normal file
15
SECURITY_CONTACTS
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# Defined below are the security contacts for this repo.
|
||||||
|
#
|
||||||
|
# They are the contact point for the Product Security Committee to reach out
|
||||||
|
# to for triaging and handling of incoming issues.
|
||||||
|
#
|
||||||
|
# The below names agree to abide by the
|
||||||
|
# [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy)
|
||||||
|
# and will be removed and replaced if they violate that agreement.
|
||||||
|
#
|
||||||
|
# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE
|
||||||
|
# INSTRUCTIONS AT https://kubernetes.io/security/
|
||||||
|
mattymo
|
||||||
|
floryut
|
||||||
|
oomichi
|
||||||
|
cristicalin
|
282
Vagrantfile
vendored
282
Vagrantfile
vendored
|
@ -1,111 +1,271 @@
|
||||||
# -*- mode: ruby -*-
|
# -*- mode: ruby -*-
|
||||||
# # vi: set ft=ruby :
|
# # vi: set ft=ruby :
|
||||||
|
|
||||||
|
# For help on using kubespray with vagrant, check out docs/vagrant.md
|
||||||
|
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
|
|
||||||
Vagrant.require_version ">= 1.8.0"
|
Vagrant.require_version ">= 2.0.0"
|
||||||
|
|
||||||
CONFIG = File.join(File.dirname(__FILE__), "vagrant/config.rb")
|
CONFIG = File.join(File.dirname(__FILE__), ENV['KUBESPRAY_VAGRANT_CONFIG'] || 'vagrant/config.rb')
|
||||||
|
|
||||||
# Defaults for config options defined in CONFIG
|
FLATCAR_URL_TEMPLATE = "https://%s.release.flatcar-linux.net/amd64-usr/current/flatcar_production_vagrant.json"
|
||||||
$num_instances = 3
|
|
||||||
$instance_name_prefix = "k8s"
|
|
||||||
$vm_gui = false
|
|
||||||
$vm_memory = 1536
|
|
||||||
$vm_cpus = 1
|
|
||||||
$shared_folders = {}
|
|
||||||
$forwarded_ports = {}
|
|
||||||
$subnet = "172.17.8"
|
|
||||||
$box = "bento/ubuntu-14.04"
|
|
||||||
|
|
||||||
host_vars = {}
|
# Uniq disk UUID for libvirt
|
||||||
|
DISK_UUID = Time.now.utc.to_i
|
||||||
|
|
||||||
|
SUPPORTED_OS = {
|
||||||
|
"flatcar-stable" => {box: "flatcar-stable", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["stable"]},
|
||||||
|
"flatcar-beta" => {box: "flatcar-beta", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["beta"]},
|
||||||
|
"flatcar-alpha" => {box: "flatcar-alpha", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["alpha"]},
|
||||||
|
"flatcar-edge" => {box: "flatcar-edge", user: "core", box_url: FLATCAR_URL_TEMPLATE % ["edge"]},
|
||||||
|
"ubuntu1604" => {box: "generic/ubuntu1604", user: "vagrant"},
|
||||||
|
"ubuntu1804" => {box: "generic/ubuntu1804", user: "vagrant"},
|
||||||
|
"ubuntu2004" => {box: "generic/ubuntu2004", user: "vagrant"},
|
||||||
|
"centos" => {box: "centos/7", user: "vagrant"},
|
||||||
|
"centos-bento" => {box: "bento/centos-7.6", user: "vagrant"},
|
||||||
|
"centos8" => {box: "centos/8", user: "vagrant"},
|
||||||
|
"centos8-bento" => {box: "bento/centos-8", user: "vagrant"},
|
||||||
|
"almalinux8" => {box: "almalinux/8", user: "vagrant"},
|
||||||
|
"almalinux8-bento" => {box: "bento/almalinux-8", user: "vagrant"},
|
||||||
|
"rockylinux8" => {box: "generic/rocky8", user: "vagrant"},
|
||||||
|
"fedora35" => {box: "fedora/35-cloud-base", user: "vagrant"},
|
||||||
|
"fedora36" => {box: "fedora/36-cloud-base", user: "vagrant"},
|
||||||
|
"opensuse" => {box: "opensuse/Leap-15.4.x86_64", user: "vagrant"},
|
||||||
|
"opensuse-tumbleweed" => {box: "opensuse/Tumbleweed.x86_64", user: "vagrant"},
|
||||||
|
"oraclelinux" => {box: "generic/oracle7", user: "vagrant"},
|
||||||
|
"oraclelinux8" => {box: "generic/oracle8", user: "vagrant"},
|
||||||
|
"rhel7" => {box: "generic/rhel7", user: "vagrant"},
|
||||||
|
"rhel8" => {box: "generic/rhel8", user: "vagrant"},
|
||||||
|
}
|
||||||
|
|
||||||
if File.exist?(CONFIG)
|
if File.exist?(CONFIG)
|
||||||
require CONFIG
|
require CONFIG
|
||||||
end
|
end
|
||||||
|
|
||||||
# if $inventory is not set, try to use example
|
# Defaults for config options defined in CONFIG
|
||||||
$inventory = File.join(File.dirname(__FILE__), "inventory") if ! $inventory
|
$num_instances ||= 3
|
||||||
|
$instance_name_prefix ||= "k8s"
|
||||||
|
$vm_gui ||= false
|
||||||
|
$vm_memory ||= 2048
|
||||||
|
$vm_cpus ||= 2
|
||||||
|
$shared_folders ||= {}
|
||||||
|
$forwarded_ports ||= {}
|
||||||
|
$subnet ||= "172.18.8"
|
||||||
|
$subnet_ipv6 ||= "fd3c:b398:0698:0756"
|
||||||
|
$os ||= "ubuntu1804"
|
||||||
|
$network_plugin ||= "flannel"
|
||||||
|
# Setting multi_networking to true will install Multus: https://github.com/intel/multus-cni
|
||||||
|
$multi_networking ||= "False"
|
||||||
|
$download_run_once ||= "True"
|
||||||
|
$download_force_cache ||= "False"
|
||||||
|
# The first three nodes are etcd servers
|
||||||
|
$etcd_instances ||= $num_instances
|
||||||
|
# The first two nodes are kube masters
|
||||||
|
$kube_master_instances ||= $num_instances == 1 ? $num_instances : ($num_instances - 1)
|
||||||
|
# All nodes are kube nodes
|
||||||
|
$kube_node_instances ||= $num_instances
|
||||||
|
# The following only works when using the libvirt provider
|
||||||
|
$kube_node_instances_with_disks ||= false
|
||||||
|
$kube_node_instances_with_disks_size ||= "20G"
|
||||||
|
$kube_node_instances_with_disks_number ||= 2
|
||||||
|
$override_disk_size ||= false
|
||||||
|
$disk_size ||= "20GB"
|
||||||
|
$local_path_provisioner_enabled ||= "False"
|
||||||
|
$local_path_provisioner_claim_root ||= "/opt/local-path-provisioner/"
|
||||||
|
$libvirt_nested ||= false
|
||||||
|
# boolean or string (e.g. "-vvv")
|
||||||
|
$ansible_verbosity ||= false
|
||||||
|
$ansible_tags ||= ENV['VAGRANT_ANSIBLE_TAGS'] || ""
|
||||||
|
|
||||||
# if $inventory has a hosts file use it, otherwise copy over vars etc
|
$playbook ||= "cluster.yml"
|
||||||
# to where vagrant expects dynamic inventory to be.
|
|
||||||
if ! File.exist?(File.join(File.dirname($inventory), "hosts"))
|
host_vars = {}
|
||||||
$vagrant_ansible = File.join(File.dirname(__FILE__), ".vagrant",
|
|
||||||
"provisioners", "ansible")
|
$box = SUPPORTED_OS[$os][:box]
|
||||||
|
# if $inventory is not set, try to use example
|
||||||
|
$inventory = "inventory/sample" if ! $inventory
|
||||||
|
$inventory = File.absolute_path($inventory, File.dirname(__FILE__))
|
||||||
|
|
||||||
|
# if $inventory has a hosts.ini file use it, otherwise copy over
|
||||||
|
# vars etc to where vagrant expects dynamic inventory to be
|
||||||
|
if ! File.exist?(File.join(File.dirname($inventory), "hosts.ini"))
|
||||||
|
$vagrant_ansible = File.join(File.dirname(__FILE__), ".vagrant", "provisioners", "ansible")
|
||||||
FileUtils.mkdir_p($vagrant_ansible) if ! File.exist?($vagrant_ansible)
|
FileUtils.mkdir_p($vagrant_ansible) if ! File.exist?($vagrant_ansible)
|
||||||
if ! File.exist?(File.join($vagrant_ansible,"inventory"))
|
$vagrant_inventory = File.join($vagrant_ansible,"inventory")
|
||||||
FileUtils.ln_s($inventory, $vagrant_ansible)
|
FileUtils.rm_f($vagrant_inventory)
|
||||||
|
FileUtils.ln_s($inventory, $vagrant_inventory)
|
||||||
|
end
|
||||||
|
|
||||||
|
if Vagrant.has_plugin?("vagrant-proxyconf")
|
||||||
|
$no_proxy = ENV['NO_PROXY'] || ENV['no_proxy'] || "127.0.0.1,localhost"
|
||||||
|
(1..$num_instances).each do |i|
|
||||||
|
$no_proxy += ",#{$subnet}.#{i+100}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Vagrant.configure("2") do |config|
|
Vagrant.configure("2") do |config|
|
||||||
# always use Vagrants insecure key
|
|
||||||
config.ssh.insert_key = false
|
|
||||||
config.vm.box = $box
|
config.vm.box = $box
|
||||||
|
if SUPPORTED_OS[$os].has_key? :box_url
|
||||||
|
config.vm.box_url = SUPPORTED_OS[$os][:box_url]
|
||||||
|
end
|
||||||
|
config.ssh.username = SUPPORTED_OS[$os][:user]
|
||||||
|
|
||||||
# plugin conflict
|
# plugin conflict
|
||||||
if Vagrant.has_plugin?("vagrant-vbguest") then
|
if Vagrant.has_plugin?("vagrant-vbguest") then
|
||||||
config.vbguest.auto_update = false
|
config.vbguest.auto_update = false
|
||||||
end
|
end
|
||||||
|
|
||||||
(1..$num_instances).each do |i|
|
# always use Vagrants insecure key
|
||||||
config.vm.define vm_name = "%s-%02d" % [$instance_name_prefix, i] do |config|
|
config.ssh.insert_key = false
|
||||||
config.vm.hostname = vm_name
|
|
||||||
|
|
||||||
if $expose_docker_tcp
|
if ($override_disk_size)
|
||||||
config.vm.network "forwarded_port", guest: 2375, host: ($expose_docker_tcp + i - 1), auto_correct: true
|
unless Vagrant.has_plugin?("vagrant-disksize")
|
||||||
|
system "vagrant plugin install vagrant-disksize"
|
||||||
|
end
|
||||||
|
config.disksize.size = $disk_size
|
||||||
end
|
end
|
||||||
|
|
||||||
$forwarded_ports.each do |guest, host|
|
(1..$num_instances).each do |i|
|
||||||
config.vm.network "forwarded_port", guest: guest, host: host, auto_correct: true
|
config.vm.define vm_name = "%s-%01d" % [$instance_name_prefix, i] do |node|
|
||||||
|
|
||||||
|
node.vm.hostname = vm_name
|
||||||
|
|
||||||
|
if Vagrant.has_plugin?("vagrant-proxyconf")
|
||||||
|
node.proxy.http = ENV['HTTP_PROXY'] || ENV['http_proxy'] || ""
|
||||||
|
node.proxy.https = ENV['HTTPS_PROXY'] || ENV['https_proxy'] || ""
|
||||||
|
node.proxy.no_proxy = $no_proxy
|
||||||
end
|
end
|
||||||
|
|
||||||
["vmware_fusion", "vmware_workstation"].each do |vmware|
|
["vmware_fusion", "vmware_workstation"].each do |vmware|
|
||||||
config.vm.provider vmware do |v|
|
node.vm.provider vmware do |v|
|
||||||
v.vmx['memsize'] = $vm_memory
|
v.vmx['memsize'] = $vm_memory
|
||||||
v.vmx['numvcpus'] = $vm_cpus
|
v.vmx['numvcpus'] = $vm_cpus
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
config.vm.provider :virtualbox do |vb|
|
node.vm.provider :virtualbox do |vb|
|
||||||
vb.gui = $vm_gui
|
|
||||||
vb.memory = $vm_memory
|
vb.memory = $vm_memory
|
||||||
vb.cpus = $vm_cpus
|
vb.cpus = $vm_cpus
|
||||||
|
vb.gui = $vm_gui
|
||||||
|
vb.linked_clone = true
|
||||||
|
vb.customize ["modifyvm", :id, "--vram", "8"] # ubuntu defaults to 256 MB which is a waste of precious RAM
|
||||||
|
vb.customize ["modifyvm", :id, "--audio", "none"]
|
||||||
|
end
|
||||||
|
|
||||||
|
node.vm.provider :libvirt do |lv|
|
||||||
|
lv.nested = $libvirt_nested
|
||||||
|
lv.cpu_mode = "host-model"
|
||||||
|
lv.memory = $vm_memory
|
||||||
|
lv.cpus = $vm_cpus
|
||||||
|
lv.default_prefix = 'kubespray'
|
||||||
|
# Fix kernel panic on fedora 28
|
||||||
|
if $os == "fedora"
|
||||||
|
lv.cpu_mode = "host-passthrough"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if $kube_node_instances_with_disks
|
||||||
|
# Libvirt
|
||||||
|
driverletters = ('a'..'z').to_a
|
||||||
|
node.vm.provider :libvirt do |lv|
|
||||||
|
# always make /dev/sd{a/b/c} so that CI can ensure that
|
||||||
|
# virtualbox and libvirt will have the same devices to use for OSDs
|
||||||
|
(1..$kube_node_instances_with_disks_number).each do |d|
|
||||||
|
lv.storage :file, :device => "hd#{driverletters[d]}", :path => "disk-#{i}-#{d}-#{DISK_UUID}.disk", :size => $kube_node_instances_with_disks_size, :bus => "scsi"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if $expose_docker_tcp
|
||||||
|
node.vm.network "forwarded_port", guest: 2375, host: ($expose_docker_tcp + i - 1), auto_correct: true
|
||||||
|
end
|
||||||
|
|
||||||
|
$forwarded_ports.each do |guest, host|
|
||||||
|
node.vm.network "forwarded_port", guest: guest, host: host, auto_correct: true
|
||||||
|
end
|
||||||
|
|
||||||
|
if ["rhel7","rhel8"].include? $os
|
||||||
|
# Vagrant synced_folder rsync options cannot be used for RHEL boxes as Rsync package cannot
|
||||||
|
# be installed until the host is registered with a valid Red Hat support subscription
|
||||||
|
node.vm.synced_folder ".", "/vagrant", disabled: false
|
||||||
|
$shared_folders.each do |src, dst|
|
||||||
|
node.vm.synced_folder src, dst
|
||||||
|
end
|
||||||
|
else
|
||||||
|
node.vm.synced_folder ".", "/vagrant", disabled: false, type: "rsync", rsync__args: ['--verbose', '--archive', '--delete', '-z'] , rsync__exclude: ['.git','venv']
|
||||||
|
$shared_folders.each do |src, dst|
|
||||||
|
node.vm.synced_folder src, dst, type: "rsync", rsync__args: ['--verbose', '--archive', '--delete', '-z']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ip = "#{$subnet}.#{i+100}"
|
ip = "#{$subnet}.#{i+100}"
|
||||||
host_vars[vm_name] = {
|
node.vm.network :private_network, ip: ip,
|
||||||
"ip" => ip,
|
:libvirt__guest_ipv6 => 'yes',
|
||||||
#"access_ip" => ip,
|
:libvirt__ipv6_address => "#{$subnet_ipv6}::#{i+100}",
|
||||||
"flannel_interface" => ip,
|
:libvirt__ipv6_prefix => "64",
|
||||||
"flannel_backend_type" => "host-gw",
|
:libvirt__forward_mode => "none",
|
||||||
"local_release_dir" => "/vagrant/temp",
|
:libvirt__dhcp_enabled => false
|
||||||
"download_run_once" => "True"
|
|
||||||
}
|
|
||||||
config.vm.network :private_network, ip: ip
|
|
||||||
|
|
||||||
# Only execute once the Ansible provisioner,
|
# Disable swap for each vm
|
||||||
# when all the machines are up and ready.
|
node.vm.provision "shell", inline: "swapoff -a"
|
||||||
if i == $num_instances
|
|
||||||
config.vm.provision "ansible" do |ansible|
|
# ubuntu1804 and ubuntu2004 have IPv6 explicitly disabled. This undoes that.
|
||||||
ansible.playbook = "cluster.yml"
|
if ["ubuntu1804", "ubuntu2004"].include? $os
|
||||||
if File.exist?(File.join(File.dirname($inventory), "hosts"))
|
node.vm.provision "shell", inline: "rm -f /etc/modprobe.d/local.conf"
|
||||||
ansible.inventory_path = $inventory
|
node.vm.provision "shell", inline: "sed -i '/net.ipv6.conf.all.disable_ipv6/d' /etc/sysctl.d/99-sysctl.conf /etc/sysctl.conf"
|
||||||
end
|
end
|
||||||
ansible.sudo = true
|
|
||||||
ansible.limit = "all"
|
# Disable firewalld on oraclelinux/redhat vms
|
||||||
|
if ["oraclelinux","oraclelinux8","rhel7","rhel8"].include? $os
|
||||||
|
node.vm.provision "shell", inline: "systemctl stop firewalld; systemctl disable firewalld"
|
||||||
|
end
|
||||||
|
|
||||||
|
host_vars[vm_name] = {
|
||||||
|
"ip": ip,
|
||||||
|
"flannel_interface": "eth1",
|
||||||
|
"kube_network_plugin": $network_plugin,
|
||||||
|
"kube_network_plugin_multus": $multi_networking,
|
||||||
|
"download_run_once": $download_run_once,
|
||||||
|
"download_localhost": "False",
|
||||||
|
"download_cache_dir": ENV['HOME'] + "/kubespray_cache",
|
||||||
|
# Make kubespray cache even when download_run_once is false
|
||||||
|
"download_force_cache": $download_force_cache,
|
||||||
|
# Keeping the cache on the nodes can improve provisioning speed while debugging kubespray
|
||||||
|
"download_keep_remote_cache": "False",
|
||||||
|
"docker_rpm_keepcache": "1",
|
||||||
|
# These two settings will put kubectl and admin.config in $inventory/artifacts
|
||||||
|
"kubeconfig_localhost": "True",
|
||||||
|
"kubectl_localhost": "True",
|
||||||
|
"local_path_provisioner_enabled": "#{$local_path_provisioner_enabled}",
|
||||||
|
"local_path_provisioner_claim_root": "#{$local_path_provisioner_claim_root}",
|
||||||
|
"ansible_ssh_user": SUPPORTED_OS[$os][:user]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Only execute the Ansible provisioner once, when all the machines are up and ready.
|
||||||
|
# And limit the action to gathering facts, the full playbook is going to be ran by testcases_run.sh
|
||||||
|
if i == $num_instances
|
||||||
|
node.vm.provision "ansible" do |ansible|
|
||||||
|
ansible.playbook = $playbook
|
||||||
|
ansible.verbose = $ansible_verbosity
|
||||||
|
$ansible_inventory_path = File.join( $inventory, "hosts.ini")
|
||||||
|
if File.exist?($ansible_inventory_path)
|
||||||
|
ansible.inventory_path = $ansible_inventory_path
|
||||||
|
end
|
||||||
|
ansible.become = true
|
||||||
|
ansible.limit = "all,localhost"
|
||||||
ansible.host_key_checking = false
|
ansible.host_key_checking = false
|
||||||
ansible.raw_arguments = ["--forks=#{$num_instances}"]
|
ansible.raw_arguments = ["--forks=#{$num_instances}", "--flush-cache", "-e ansible_become_pass=vagrant"]
|
||||||
ansible.host_vars = host_vars
|
ansible.host_vars = host_vars
|
||||||
#ansible.tags = ['download']
|
if $ansible_tags != ""
|
||||||
|
ansible.tags = [$ansible_tags]
|
||||||
|
end
|
||||||
ansible.groups = {
|
ansible.groups = {
|
||||||
# The first three nodes should be etcd servers
|
"etcd" => ["#{$instance_name_prefix}-[1:#{$etcd_instances}]"],
|
||||||
"etcd" => ["#{$instance_name_prefix}-0[1:3]"],
|
"kube_control_plane" => ["#{$instance_name_prefix}-[1:#{$kube_master_instances}]"],
|
||||||
# The first two nodes should be masters
|
"kube_node" => ["#{$instance_name_prefix}-[1:#{$kube_node_instances}]"],
|
||||||
"kube-master" => ["#{$instance_name_prefix}-0[1:2]"],
|
"k8s_cluster:children" => ["kube_control_plane", "kube_node"],
|
||||||
# all nodes should be kube nodes
|
|
||||||
"kube-node" => ["#{$instance_name_prefix}-0[1:#{$num_instances}]"],
|
|
||||||
"k8s-cluster:children" => ["kube-master", "kube-node"],
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
2
_config.yml
Normal file
2
_config.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
theme: jekyll-theme-slate
|
18
ansible.cfg
18
ansible.cfg
|
@ -1,4 +1,22 @@
|
||||||
[ssh_connection]
|
[ssh_connection]
|
||||||
pipelining=True
|
pipelining=True
|
||||||
|
ansible_ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100 -o UserKnownHostsFile=/dev/null
|
||||||
|
#control_path = ~/.ssh/ansible-%%r@%%h:%%p
|
||||||
[defaults]
|
[defaults]
|
||||||
|
# https://github.com/ansible/ansible/issues/56930 (to ignore group names with - and .)
|
||||||
|
force_valid_group_names = ignore
|
||||||
|
|
||||||
host_key_checking=False
|
host_key_checking=False
|
||||||
|
gathering = smart
|
||||||
|
fact_caching = jsonfile
|
||||||
|
fact_caching_connection = /tmp
|
||||||
|
fact_caching_timeout = 86400
|
||||||
|
stdout_callback = default
|
||||||
|
display_skipped_hosts = no
|
||||||
|
library = ./library
|
||||||
|
callbacks_enabled = profile_tasks,ara_default
|
||||||
|
roles_path = roles:$VIRTUAL_ENV/usr/local/share/kubespray/roles:$VIRTUAL_ENV/usr/local/share/ansible/roles:/usr/share/kubespray/roles
|
||||||
|
deprecation_warnings=False
|
||||||
|
inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo, .creds, .gpg
|
||||||
|
[inventory]
|
||||||
|
ignore_patterns = artifacts, credentials
|
||||||
|
|
33
ansible_version.yml
Normal file
33
ansible_version.yml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
gather_facts: false
|
||||||
|
become: no
|
||||||
|
vars:
|
||||||
|
minimal_ansible_version: 2.11.0
|
||||||
|
maximal_ansible_version: 2.14.0
|
||||||
|
ansible_connection: local
|
||||||
|
tags: always
|
||||||
|
tasks:
|
||||||
|
- name: "Check {{ minimal_ansible_version }} <= Ansible version < {{ maximal_ansible_version }}"
|
||||||
|
assert:
|
||||||
|
msg: "Ansible must be between {{ minimal_ansible_version }} and {{ maximal_ansible_version }} exclusive"
|
||||||
|
that:
|
||||||
|
- ansible_version.string is version(minimal_ansible_version, ">=")
|
||||||
|
- ansible_version.string is version(maximal_ansible_version, "<")
|
||||||
|
tags:
|
||||||
|
- check
|
||||||
|
|
||||||
|
- name: "Check that python netaddr is installed"
|
||||||
|
assert:
|
||||||
|
msg: "Python netaddr is not present"
|
||||||
|
that: "'127.0.0.1' | ipaddr"
|
||||||
|
tags:
|
||||||
|
- check
|
||||||
|
|
||||||
|
# CentOS 7 provides too old jinja version
|
||||||
|
- name: "Check that jinja is not too old (install via pip)"
|
||||||
|
assert:
|
||||||
|
msg: "Your Jinja version is too old, install via pip"
|
||||||
|
that: "{% set test %}It works{% endset %}{{ test == 'It works' }}"
|
||||||
|
tags:
|
||||||
|
- check
|
131
cluster.yml
131
cluster.yml
|
@ -1,36 +1,131 @@
|
||||||
---
|
---
|
||||||
- hosts: all
|
- name: Check ansible version
|
||||||
|
import_playbook: ansible_version.yml
|
||||||
|
|
||||||
|
- name: Ensure compatibility with old groups
|
||||||
|
import_playbook: legacy_groups.yml
|
||||||
|
|
||||||
|
- hosts: bastion[0]
|
||||||
|
gather_facts: False
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
|
roles:
|
||||||
|
- { role: kubespray-defaults }
|
||||||
|
- { role: bastion-ssh-config, tags: ["localhost", "bastion"] }
|
||||||
|
|
||||||
|
- hosts: k8s_cluster:etcd
|
||||||
|
strategy: linear
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
gather_facts: false
|
gather_facts: false
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
roles:
|
roles:
|
||||||
- bootstrap-os
|
- { role: kubespray-defaults }
|
||||||
tags:
|
- { role: bootstrap-os, tags: bootstrap-os}
|
||||||
- bootstrap-os
|
|
||||||
|
|
||||||
|
- name: Gather facts
|
||||||
|
tags: always
|
||||||
|
import_playbook: facts.yml
|
||||||
|
|
||||||
- hosts: all
|
- hosts: k8s_cluster:etcd
|
||||||
gather_facts: true
|
gather_facts: False
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
- hosts: etcd:!k8s-cluster
|
environment: "{{ proxy_disable_env }}"
|
||||||
roles:
|
roles:
|
||||||
|
- { role: kubespray-defaults }
|
||||||
- { role: kubernetes/preinstall, tags: preinstall }
|
- { role: kubernetes/preinstall, tags: preinstall }
|
||||||
- { role: etcd, tags: etcd }
|
- { role: "container-engine", tags: "container-engine", when: deploy_container_engine }
|
||||||
|
- { role: download, tags: download, when: "not skip_downloads" }
|
||||||
|
|
||||||
- hosts: k8s-cluster
|
- hosts: etcd:kube_control_plane
|
||||||
|
gather_facts: False
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
roles:
|
roles:
|
||||||
- { role: kubernetes/preinstall, tags: preinstall }
|
- { role: kubespray-defaults }
|
||||||
- { role: etcd, tags: etcd }
|
- role: etcd
|
||||||
|
tags: etcd
|
||||||
|
vars:
|
||||||
|
etcd_cluster_setup: true
|
||||||
|
etcd_events_cluster_setup: "{{ etcd_events_cluster_enabled }}"
|
||||||
|
when: etcd_deployment_type != "kubeadm"
|
||||||
|
|
||||||
|
- hosts: k8s_cluster
|
||||||
|
gather_facts: False
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
|
roles:
|
||||||
|
- { role: kubespray-defaults }
|
||||||
|
- role: etcd
|
||||||
|
tags: etcd
|
||||||
|
vars:
|
||||||
|
etcd_cluster_setup: false
|
||||||
|
etcd_events_cluster_setup: false
|
||||||
|
when:
|
||||||
|
- etcd_deployment_type != "kubeadm"
|
||||||
|
- kube_network_plugin in ["calico", "flannel", "canal", "cilium"] or cilium_deploy_additionally | default(false) | bool
|
||||||
|
- kube_network_plugin != "calico" or calico_datastore == "etcd"
|
||||||
|
|
||||||
|
- hosts: k8s_cluster
|
||||||
|
gather_facts: False
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
|
roles:
|
||||||
|
- { role: kubespray-defaults }
|
||||||
- { role: kubernetes/node, tags: node }
|
- { role: kubernetes/node, tags: node }
|
||||||
|
|
||||||
|
- hosts: kube_control_plane
|
||||||
|
gather_facts: False
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
|
roles:
|
||||||
|
- { role: kubespray-defaults }
|
||||||
|
- { role: kubernetes/control-plane, tags: master }
|
||||||
|
- { role: kubernetes/client, tags: client }
|
||||||
|
- { role: kubernetes-apps/cluster_roles, tags: cluster-roles }
|
||||||
|
|
||||||
|
- hosts: k8s_cluster
|
||||||
|
gather_facts: False
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
|
roles:
|
||||||
|
- { role: kubespray-defaults }
|
||||||
|
- { role: kubernetes/kubeadm, tags: kubeadm}
|
||||||
|
- { role: kubernetes/node-label, tags: node-label }
|
||||||
- { role: network_plugin, tags: network }
|
- { role: network_plugin, tags: network }
|
||||||
|
|
||||||
- hosts: kube-master
|
- hosts: calico_rr
|
||||||
|
gather_facts: False
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
roles:
|
roles:
|
||||||
- { role: kubernetes/preinstall, tags: preinstall }
|
- { role: kubespray-defaults }
|
||||||
- { role: kubernetes/master, tags: master }
|
- { role: network_plugin/calico/rr, tags: ['network', 'calico_rr'] }
|
||||||
|
|
||||||
- hosts: k8s-cluster
|
- hosts: kube_control_plane[0]
|
||||||
|
gather_facts: False
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
roles:
|
roles:
|
||||||
- { role: dnsmasq, tags: dnsmasq }
|
- { role: kubespray-defaults }
|
||||||
|
- { role: win_nodes/kubernetes_patch, tags: ["master", "win_nodes"] }
|
||||||
|
|
||||||
- hosts: kube-master[0]
|
- hosts: kube_control_plane
|
||||||
|
gather_facts: False
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
roles:
|
roles:
|
||||||
|
- { role: kubespray-defaults }
|
||||||
|
- { role: kubernetes-apps/external_cloud_controller, tags: external-cloud-controller }
|
||||||
|
- { role: kubernetes-apps/network_plugin, tags: network }
|
||||||
|
- { role: kubernetes-apps/policy_controller, tags: policy-controller }
|
||||||
|
- { role: kubernetes-apps/ingress_controller, tags: ingress-controller }
|
||||||
|
- { role: kubernetes-apps/external_provisioner, tags: external-provisioner }
|
||||||
- { role: kubernetes-apps, tags: apps }
|
- { role: kubernetes-apps, tags: apps }
|
||||||
|
|
||||||
|
- name: Apply resolv.conf changes now that cluster DNS is up
|
||||||
|
hosts: k8s_cluster
|
||||||
|
gather_facts: False
|
||||||
|
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
|
||||||
|
environment: "{{ proxy_disable_env }}"
|
||||||
|
roles:
|
||||||
|
- { role: kubespray-defaults }
|
||||||
|
- { role: kubernetes/preinstall, when: "dns_mode != 'none' and resolvconf_mode == 'host_resolvconf'", tags: resolvconf, dns_late: true }
|
||||||
|
|
|
@ -1,59 +1,3 @@
|
||||||
## Kubernetes Community Code of Conduct
|
# Kubernetes Community Code of Conduct
|
||||||
|
|
||||||
### Contributor Code of Conduct
|
Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md)
|
||||||
|
|
||||||
As contributors and maintainers of this project, and in the interest of fostering
|
|
||||||
an open and welcoming community, we pledge to respect all people who contribute
|
|
||||||
through reporting issues, posting feature requests, updating documentation,
|
|
||||||
submitting pull requests or patches, and other activities.
|
|
||||||
|
|
||||||
We are committed to making participation in this project a harassment-free experience for
|
|
||||||
everyone, regardless of level of experience, gender, gender identity and expression,
|
|
||||||
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
|
|
||||||
religion, or nationality.
|
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery
|
|
||||||
* Personal attacks
|
|
||||||
* Trolling or insulting/derogatory comments
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing other's private information, such as physical or electronic addresses,
|
|
||||||
without explicit permission
|
|
||||||
* Other unethical or unprofessional conduct.
|
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or reject
|
|
||||||
comments, commits, code, wiki edits, issues, and other contributions that are not
|
|
||||||
aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers
|
|
||||||
commit themselves to fairly and consistently applying these principles to every aspect
|
|
||||||
of managing this project. Project maintainers who do not follow or enforce the Code of
|
|
||||||
Conduct may be permanently removed from the project team.
|
|
||||||
|
|
||||||
This code of conduct applies both within project spaces and in public spaces
|
|
||||||
when an individual is representing the project or its community.
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
|
|
||||||
opening an issue or contacting one or more of the project maintainers.
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the Contributor Covenant
|
|
||||||
(http://contributor-covenant.org), version 1.2.0, available at
|
|
||||||
http://contributor-covenant.org/version/1/2/0/
|
|
||||||
|
|
||||||
### Kubernetes Events Code of Conduct
|
|
||||||
|
|
||||||
Kubernetes events are working conferences intended for professional networking and collaboration in the
|
|
||||||
Kubernetes community. Attendees are expected to behave according to professional standards and in accordance
|
|
||||||
with their employer's policies on appropriate workplace behavior.
|
|
||||||
|
|
||||||
While at Kubernetes events or related social networking opportunities, attendees should not engage in
|
|
||||||
discriminatory or offensive speech or actions regarding gender, sexuality, race, or religion. Speakers should
|
|
||||||
be especially aware of these concerns.
|
|
||||||
|
|
||||||
The Kubernetes team does not condone any statements by speakers contrary to these standards. The Kubernetes
|
|
||||||
team reserves the right to deny entrance and/or eject from an event (without refund) any individual found to
|
|
||||||
be engaging in discriminatory or offensive speech or actions.
|
|
||||||
|
|
||||||
Please bring any concerns to to the immediate attention of Kubernetes event staff
|
|
||||||
|
|
||||||
|
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/code-of-conduct.md?pixel)]()
|
|
||||||
|
|
27
contrib/aws_iam/kubernetes-master-policy.json
Normal file
27
contrib/aws_iam/kubernetes-master-policy.json
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": ["ec2:*"],
|
||||||
|
"Resource": ["*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": ["elasticloadbalancing:*"],
|
||||||
|
"Resource": ["*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": ["route53:*"],
|
||||||
|
"Resource": ["*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": "s3:*",
|
||||||
|
"Resource": [
|
||||||
|
"arn:aws:s3:::kubernetes-*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
10
contrib/aws_iam/kubernetes-master-role.json
Normal file
10
contrib/aws_iam/kubernetes-master-role.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Principal": { "Service": "ec2.amazonaws.com"},
|
||||||
|
"Action": "sts:AssumeRole"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
45
contrib/aws_iam/kubernetes-minion-policy.json
Normal file
45
contrib/aws_iam/kubernetes-minion-policy.json
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": "s3:*",
|
||||||
|
"Resource": [
|
||||||
|
"arn:aws:s3:::kubernetes-*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": "ec2:Describe*",
|
||||||
|
"Resource": "*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": "ec2:AttachVolume",
|
||||||
|
"Resource": "*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": "ec2:DetachVolume",
|
||||||
|
"Resource": "*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": ["route53:*"],
|
||||||
|
"Resource": ["*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"ecr:GetAuthorizationToken",
|
||||||
|
"ecr:BatchCheckLayerAvailability",
|
||||||
|
"ecr:GetDownloadUrlForLayer",
|
||||||
|
"ecr:GetRepositoryPolicy",
|
||||||
|
"ecr:DescribeRepositories",
|
||||||
|
"ecr:ListImages",
|
||||||
|
"ecr:BatchGetImage"
|
||||||
|
],
|
||||||
|
"Resource": "*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
10
contrib/aws_iam/kubernetes-minion-role.json
Normal file
10
contrib/aws_iam/kubernetes-minion-role.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Principal": { "Service": "ec2.amazonaws.com"},
|
||||||
|
"Action": "sts:AssumeRole"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
76
contrib/aws_inventory/kubespray-aws-inventory.py
Executable file
76
contrib/aws_inventory/kubespray-aws-inventory.py
Executable file
|
@ -0,0 +1,76 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import boto3
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
|
||||||
|
class SearchEC2Tags(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.parse_args()
|
||||||
|
if self.args.list:
|
||||||
|
self.search_tags()
|
||||||
|
if self.args.host:
|
||||||
|
data = {}
|
||||||
|
print(json.dumps(data, indent=2))
|
||||||
|
|
||||||
|
def parse_args(self):
|
||||||
|
|
||||||
|
##Check if VPC_VISIBILITY is set, if not default to private
|
||||||
|
if "VPC_VISIBILITY" in os.environ:
|
||||||
|
self.vpc_visibility = os.environ['VPC_VISIBILITY']
|
||||||
|
else:
|
||||||
|
self.vpc_visibility = "private"
|
||||||
|
|
||||||
|
##Support --list and --host flags. We largely ignore the host one.
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--list', action='store_true', default=False, help='List instances')
|
||||||
|
parser.add_argument('--host', action='store_true', help='Get all the variables about a specific instance')
|
||||||
|
self.args = parser.parse_args()
|
||||||
|
|
||||||
|
def search_tags(self):
|
||||||
|
hosts = {}
|
||||||
|
hosts['_meta'] = { 'hostvars': {} }
|
||||||
|
|
||||||
|
##Search ec2 three times to find nodes of each group type. Relies on kubespray-role key/value.
|
||||||
|
for group in ["kube_control_plane", "kube_node", "etcd"]:
|
||||||
|
hosts[group] = []
|
||||||
|
tag_key = "kubespray-role"
|
||||||
|
tag_value = ["*"+group+"*"]
|
||||||
|
region = os.environ['REGION']
|
||||||
|
|
||||||
|
ec2 = boto3.resource('ec2', region)
|
||||||
|
filters = [{'Name': 'tag:'+tag_key, 'Values': tag_value}, {'Name': 'instance-state-name', 'Values': ['running']}]
|
||||||
|
cluster_name = os.getenv('CLUSTER_NAME')
|
||||||
|
if cluster_name:
|
||||||
|
filters.append({'Name': 'tag-key', 'Values': ['kubernetes.io/cluster/'+cluster_name]})
|
||||||
|
instances = ec2.instances.filter(Filters=filters)
|
||||||
|
for instance in instances:
|
||||||
|
|
||||||
|
##Suppose default vpc_visibility is private
|
||||||
|
dns_name = instance.private_dns_name
|
||||||
|
ansible_host = {
|
||||||
|
'ansible_ssh_host': instance.private_ip_address
|
||||||
|
}
|
||||||
|
|
||||||
|
##Override when vpc_visibility actually is public
|
||||||
|
if self.vpc_visibility == "public":
|
||||||
|
dns_name = instance.public_dns_name
|
||||||
|
ansible_host = {
|
||||||
|
'ansible_ssh_host': instance.public_ip_address
|
||||||
|
}
|
||||||
|
|
||||||
|
##Set when instance actually has node_labels
|
||||||
|
node_labels_tag = list(filter(lambda t: t['Key'] == 'kubespray-node-labels', instance.tags))
|
||||||
|
if node_labels_tag:
|
||||||
|
ansible_host['node_labels'] = dict([ label.strip().split('=') for label in node_labels_tag[0]['Value'].split(',') ])
|
||||||
|
|
||||||
|
hosts[group].append(dns_name)
|
||||||
|
hosts['_meta']['hostvars'][dns_name] = ansible_host
|
||||||
|
|
||||||
|
hosts['k8s_cluster'] = {'children':['kube_control_plane', 'kube_node']}
|
||||||
|
print(json.dumps(hosts, sort_keys=True, indent=2))
|
||||||
|
|
||||||
|
SearchEC2Tags()
|
1
contrib/aws_inventory/requirements.txt
Normal file
1
contrib/aws_inventory/requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
boto3 # Apache-2.0
|
2
contrib/azurerm/.gitignore
vendored
Normal file
2
contrib/azurerm/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.generated
|
||||||
|
/inventory
|
67
contrib/azurerm/README.md
Normal file
67
contrib/azurerm/README.md
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
# Kubernetes on Azure with Azure Resource Group Templates
|
||||||
|
|
||||||
|
Provision the base infrastructure for a Kubernetes cluster by using [Azure Resource Group Templates](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authoring-templates)
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
This will provision the base infrastructure (vnet, vms, nics, ips, ...) needed for Kubernetes in Azure into the specified
|
||||||
|
Resource Group. It will not install Kubernetes itself, this has to be done in a later step by yourself (using kubespray of course).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- [Install azure-cli](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
|
||||||
|
- [Login with azure-cli](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli?view=azure-cli-latest)
|
||||||
|
- Dedicated Resource Group created in the Azure Portal or through azure-cli
|
||||||
|
|
||||||
|
## Configuration through group_vars/all
|
||||||
|
|
||||||
|
You have to modify at least two variables in group_vars/all. The one is the **cluster_name** variable, it must be globally
|
||||||
|
unique due to some restrictions in Azure. The other one is the **ssh_public_keys** variable, it must be your ssh public
|
||||||
|
key to access your azure virtual machines. Most other variables should be self explanatory if you have some basic Kubernetes
|
||||||
|
experience.
|
||||||
|
|
||||||
|
## Bastion host
|
||||||
|
|
||||||
|
You can enable the use of a Bastion Host by changing **use_bastion** in group_vars/all to **true**. The generated
|
||||||
|
templates will then include an additional bastion VM which can then be used to connect to the masters and nodes. The option
|
||||||
|
also removes all public IPs from all other VMs.
|
||||||
|
|
||||||
|
## Generating and applying
|
||||||
|
|
||||||
|
To generate and apply the templates, call:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./apply-rg.sh <resource_group_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
If you change something in the configuration (e.g. number of nodes) later, you can call this again and Azure will
|
||||||
|
take care about creating/modifying whatever is needed.
|
||||||
|
|
||||||
|
## Clearing a resource group
|
||||||
|
|
||||||
|
If you need to delete all resources from a resource group, simply call:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./clear-rg.sh <resource_group_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
**WARNING** this really deletes everything from your resource group, including everything that was later created by you!
|
||||||
|
|
||||||
|
## Installing Ansible and the dependencies
|
||||||
|
|
||||||
|
Install Ansible according to [Ansible installation guide](/docs/ansible.md#installing-ansible)
|
||||||
|
|
||||||
|
## Generating an inventory for kubespray
|
||||||
|
|
||||||
|
After you have applied the templates, you can generate an inventory with this call:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./generate-inventory.sh <resource_group_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
It will create the file ./inventory which can then be used with kubespray, e.g.:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cd kubespray-root-dir
|
||||||
|
ansible-playbook -i contrib/azurerm/inventory -u devops --become -e "@inventory/sample/group_vars/all/all.yml" cluster.yml
|
||||||
|
```
|
19
contrib/azurerm/apply-rg.sh
Executable file
19
contrib/azurerm/apply-rg.sh
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
AZURE_RESOURCE_GROUP="$1"
|
||||||
|
|
||||||
|
if [ "$AZURE_RESOURCE_GROUP" == "" ]; then
|
||||||
|
echo "AZURE_RESOURCE_GROUP is missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ansible-playbook generate-templates.yml
|
||||||
|
|
||||||
|
az deployment group create --template-file ./.generated/network.json -g $AZURE_RESOURCE_GROUP
|
||||||
|
az deployment group create --template-file ./.generated/storage.json -g $AZURE_RESOURCE_GROUP
|
||||||
|
az deployment group create --template-file ./.generated/availability-sets.json -g $AZURE_RESOURCE_GROUP
|
||||||
|
az deployment group create --template-file ./.generated/bastion.json -g $AZURE_RESOURCE_GROUP
|
||||||
|
az deployment group create --template-file ./.generated/masters.json -g $AZURE_RESOURCE_GROUP
|
||||||
|
az deployment group create --template-file ./.generated/minions.json -g $AZURE_RESOURCE_GROUP
|
14
contrib/azurerm/clear-rg.sh
Executable file
14
contrib/azurerm/clear-rg.sh
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
AZURE_RESOURCE_GROUP="$1"
|
||||||
|
|
||||||
|
if [ "$AZURE_RESOURCE_GROUP" == "" ]; then
|
||||||
|
echo "AZURE_RESOURCE_GROUP is missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ansible-playbook generate-templates.yml
|
||||||
|
|
||||||
|
az group deployment create -g "$AZURE_RESOURCE_GROUP" --template-file ./.generated/clear-rg.json --mode Complete
|
18
contrib/azurerm/generate-inventory.sh
Executable file
18
contrib/azurerm/generate-inventory.sh
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
AZURE_RESOURCE_GROUP="$1"
|
||||||
|
|
||||||
|
if [ "$AZURE_RESOURCE_GROUP" == "" ]; then
|
||||||
|
echo "AZURE_RESOURCE_GROUP is missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# check if azure cli 2.0 exists else use azure cli 1.0
|
||||||
|
if az &>/dev/null; then
|
||||||
|
ansible-playbook generate-inventory_2.yml -e azure_resource_group="$AZURE_RESOURCE_GROUP"
|
||||||
|
elif azure &>/dev/null; then
|
||||||
|
ansible-playbook generate-inventory.yml -e azure_resource_group="$AZURE_RESOURCE_GROUP"
|
||||||
|
else
|
||||||
|
echo "Azure cli not found"
|
||||||
|
fi
|
5
contrib/azurerm/generate-inventory.yml
Normal file
5
contrib/azurerm/generate-inventory.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
gather_facts: False
|
||||||
|
roles:
|
||||||
|
- generate-inventory
|
5
contrib/azurerm/generate-inventory_2.yml
Normal file
5
contrib/azurerm/generate-inventory_2.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
gather_facts: False
|
||||||
|
roles:
|
||||||
|
- generate-inventory_2
|
5
contrib/azurerm/generate-templates.yml
Normal file
5
contrib/azurerm/generate-templates.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
gather_facts: False
|
||||||
|
roles:
|
||||||
|
- generate-templates
|
51
contrib/azurerm/group_vars/all
Normal file
51
contrib/azurerm/group_vars/all
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
# Due to some Azure limitations (ex:- Storage Account's name must be unique),
|
||||||
|
# this name must be globally unique - it will be used as a prefix for azure components
|
||||||
|
cluster_name: example
|
||||||
|
|
||||||
|
# Set this to true if you do not want to have public IPs for your masters and minions. This will provision a bastion
|
||||||
|
# node that can be used to access the masters and minions
|
||||||
|
use_bastion: false
|
||||||
|
|
||||||
|
# Set this to a preferred name that will be used as the first part of the dns name for your bastotion host. For example: k8s-bastion.<azureregion>.cloudapp.azure.com.
|
||||||
|
# This is convenient when exceptions have to be configured on a firewall to allow ssh to the given bastion host.
|
||||||
|
# bastion_domain_prefix: k8s-bastion
|
||||||
|
|
||||||
|
number_of_k8s_masters: 3
|
||||||
|
number_of_k8s_nodes: 3
|
||||||
|
|
||||||
|
masters_vm_size: Standard_A2
|
||||||
|
masters_os_disk_size: 1000
|
||||||
|
|
||||||
|
minions_vm_size: Standard_A2
|
||||||
|
minions_os_disk_size: 1000
|
||||||
|
|
||||||
|
admin_username: devops
|
||||||
|
admin_password: changeme
|
||||||
|
|
||||||
|
# MAKE SURE TO CHANGE THIS TO YOUR PUBLIC KEY to access your azure machines
|
||||||
|
ssh_public_keys:
|
||||||
|
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLRzcxbsFDdEibiyXCSdIFh7bKbXso1NqlKjEyPTptf3aBXHEhVil0lJRjGpTlpfTy7PHvXFbXIOCdv9tOmeH1uxWDDeZawgPFV6VSZ1QneCL+8bxzhjiCn8133wBSPZkN8rbFKd9eEUUBfx8ipCblYblF9FcidylwtMt5TeEmXk8yRVkPiCuEYuDplhc2H0f4PsK3pFb5aDVdaDT3VeIypnOQZZoUxHWqm6ThyHrzLJd3SrZf+RROFWW1uInIDf/SZlXojczUYoffxgT1lERfOJCHJXsqbZWugbxQBwqsVsX59+KPxFFo6nV88h3UQr63wbFx52/MXkX4WrCkAHzN ablock-vwfs@dell-lappy"
|
||||||
|
|
||||||
|
# Disable using ssh using password. Change it to false to allow to connect to ssh by password
|
||||||
|
disablePasswordAuthentication: true
|
||||||
|
|
||||||
|
# Azure CIDRs
|
||||||
|
azure_vnet_cidr: 10.0.0.0/8
|
||||||
|
azure_admin_cidr: 10.241.2.0/24
|
||||||
|
azure_masters_cidr: 10.0.4.0/24
|
||||||
|
azure_minions_cidr: 10.240.0.0/16
|
||||||
|
|
||||||
|
# Azure loadbalancer port to use to access your cluster
|
||||||
|
kube_apiserver_port: 6443
|
||||||
|
|
||||||
|
# Azure Netwoking and storage naming to use with inventory/all.yml
|
||||||
|
#azure_virtual_network_name: KubeVNET
|
||||||
|
#azure_subnet_admin_name: ad-subnet
|
||||||
|
#azure_subnet_masters_name: master-subnet
|
||||||
|
#azure_subnet_minions_name: minion-subnet
|
||||||
|
#azure_route_table_name: routetable
|
||||||
|
#azure_security_group_name: secgroup
|
||||||
|
|
||||||
|
# Storage types available are: "Standard_LRS","Premium_LRS"
|
||||||
|
#azure_storage_account_type: Standard_LRS
|
15
contrib/azurerm/roles/generate-inventory/tasks/main.yml
Normal file
15
contrib/azurerm/roles/generate-inventory/tasks/main.yml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Query Azure VMs # noqa 301
|
||||||
|
command: azure vm list-ip-address --json {{ azure_resource_group }}
|
||||||
|
register: vm_list_cmd
|
||||||
|
|
||||||
|
- name: Set vm_list
|
||||||
|
set_fact:
|
||||||
|
vm_list: "{{ vm_list_cmd.stdout }}"
|
||||||
|
|
||||||
|
- name: Generate inventory
|
||||||
|
template:
|
||||||
|
src: inventory.j2
|
||||||
|
dest: "{{ playbook_dir }}/inventory"
|
||||||
|
mode: 0644
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
{% for vm in vm_list %}
|
||||||
|
{% if not use_bastion or vm.name == 'bastion' %}
|
||||||
|
{{ vm.name }} ansible_ssh_host={{ vm.networkProfile.networkInterfaces[0].expanded.ipConfigurations[0].publicIPAddress.expanded.ipAddress }} ip={{ vm.networkProfile.networkInterfaces[0].expanded.ipConfigurations[0].privateIPAddress }}
|
||||||
|
{% else %}
|
||||||
|
{{ vm.name }} ansible_ssh_host={{ vm.networkProfile.networkInterfaces[0].expanded.ipConfigurations[0].privateIPAddress }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[kube_control_plane]
|
||||||
|
{% for vm in vm_list %}
|
||||||
|
{% if 'kube_control_plane' in vm.tags.roles %}
|
||||||
|
{{ vm.name }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[etcd]
|
||||||
|
{% for vm in vm_list %}
|
||||||
|
{% if 'etcd' in vm.tags.roles %}
|
||||||
|
{{ vm.name }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[kube_node]
|
||||||
|
{% for vm in vm_list %}
|
||||||
|
{% if 'kube_node' in vm.tags.roles %}
|
||||||
|
{{ vm.name }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[k8s_cluster:children]
|
||||||
|
kube_node
|
||||||
|
kube_control_plane
|
31
contrib/azurerm/roles/generate-inventory_2/tasks/main.yml
Normal file
31
contrib/azurerm/roles/generate-inventory_2/tasks/main.yml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Query Azure VMs IPs # noqa 301
|
||||||
|
command: az vm list-ip-addresses -o json --resource-group {{ azure_resource_group }}
|
||||||
|
register: vm_ip_list_cmd
|
||||||
|
|
||||||
|
- name: Query Azure VMs Roles # noqa 301
|
||||||
|
command: az vm list -o json --resource-group {{ azure_resource_group }}
|
||||||
|
register: vm_list_cmd
|
||||||
|
|
||||||
|
- name: Query Azure Load Balancer Public IP # noqa 301
|
||||||
|
command: az network public-ip show -o json -g {{ azure_resource_group }} -n kubernetes-api-pubip
|
||||||
|
register: lb_pubip_cmd
|
||||||
|
|
||||||
|
- name: Set VM IP, roles lists and load balancer public IP
|
||||||
|
set_fact:
|
||||||
|
vm_ip_list: "{{ vm_ip_list_cmd.stdout }}"
|
||||||
|
vm_roles_list: "{{ vm_list_cmd.stdout }}"
|
||||||
|
lb_pubip: "{{ lb_pubip_cmd.stdout }}"
|
||||||
|
|
||||||
|
- name: Generate inventory
|
||||||
|
template:
|
||||||
|
src: inventory.j2
|
||||||
|
dest: "{{ playbook_dir }}/inventory"
|
||||||
|
mode: 0644
|
||||||
|
|
||||||
|
- name: Generate Load Balancer variables
|
||||||
|
template:
|
||||||
|
src: loadbalancer_vars.j2
|
||||||
|
dest: "{{ playbook_dir }}/loadbalancer_vars.yml"
|
||||||
|
mode: 0644
|
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
{% for vm in vm_ip_list %}
|
||||||
|
{% if not use_bastion or vm.virtualMachine.name == 'bastion' %}
|
||||||
|
{{ vm.virtualMachine.name }} ansible_ssh_host={{ vm.virtualMachine.network.publicIpAddresses[0].ipAddress }} ip={{ vm.virtualMachine.network.privateIpAddresses[0] }}
|
||||||
|
{% else %}
|
||||||
|
{{ vm.virtualMachine.name }} ansible_ssh_host={{ vm.virtualMachine.network.privateIpAddresses[0] }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[kube_control_plane]
|
||||||
|
{% for vm in vm_roles_list %}
|
||||||
|
{% if 'kube_control_plane' in vm.tags.roles %}
|
||||||
|
{{ vm.name }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[etcd]
|
||||||
|
{% for vm in vm_roles_list %}
|
||||||
|
{% if 'etcd' in vm.tags.roles %}
|
||||||
|
{{ vm.name }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[kube_node]
|
||||||
|
{% for vm in vm_roles_list %}
|
||||||
|
{% if 'kube_node' in vm.tags.roles %}
|
||||||
|
{{ vm.name }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[k8s_cluster:children]
|
||||||
|
kube_node
|
||||||
|
kube_control_plane
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
## External LB example config
|
||||||
|
apiserver_loadbalancer_domain_name: {{ lb_pubip.dnsSettings.fqdn }}
|
||||||
|
loadbalancer_apiserver:
|
||||||
|
address: {{ lb_pubip.ipAddress }}
|
||||||
|
port: 6443
|
||||||
|
|
||||||
|
## Internal loadbalancers for apiservers
|
||||||
|
loadbalancer_apiserver_localhost: false
|
37
contrib/azurerm/roles/generate-templates/defaults/main.yml
Normal file
37
contrib/azurerm/roles/generate-templates/defaults/main.yml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
apiVersion: "2015-06-15"
|
||||||
|
|
||||||
|
virtualNetworkName: "{{ azure_virtual_network_name | default('KubeVNET') }}"
|
||||||
|
|
||||||
|
subnetAdminName: "{{ azure_subnet_admin_name | default('ad-subnet') }}"
|
||||||
|
subnetMastersName: "{{ azure_subnet_masters_name | default('master-subnet') }}"
|
||||||
|
subnetMinionsName: "{{ azure_subnet_minions_name | default('minion-subnet') }}"
|
||||||
|
|
||||||
|
routeTableName: "{{ azure_route_table_name | default('routetable') }}"
|
||||||
|
securityGroupName: "{{ azure_security_group_name | default('secgroup') }}"
|
||||||
|
|
||||||
|
nameSuffix: "{{ cluster_name }}"
|
||||||
|
|
||||||
|
availabilitySetMasters: "master-avs"
|
||||||
|
availabilitySetMinions: "minion-avs"
|
||||||
|
|
||||||
|
faultDomainCount: 3
|
||||||
|
updateDomainCount: 10
|
||||||
|
|
||||||
|
bastionVmSize: Standard_A0
|
||||||
|
bastionVMName: bastion
|
||||||
|
bastionIPAddressName: bastion-pubip
|
||||||
|
|
||||||
|
disablePasswordAuthentication: true
|
||||||
|
|
||||||
|
sshKeyPath: "/home/{{admin_username}}/.ssh/authorized_keys"
|
||||||
|
|
||||||
|
imageReference:
|
||||||
|
publisher: "OpenLogic"
|
||||||
|
offer: "CentOS"
|
||||||
|
sku: "7.5"
|
||||||
|
version: "latest"
|
||||||
|
imageReferenceJson: "{{imageReference|to_json}}"
|
||||||
|
|
||||||
|
storageAccountName: "sa{{nameSuffix | replace('-', '')}}"
|
||||||
|
storageAccountType: "{{ azure_storage_account_type | default('Standard_LRS') }}"
|
25
contrib/azurerm/roles/generate-templates/tasks/main.yml
Normal file
25
contrib/azurerm/roles/generate-templates/tasks/main.yml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
- name: Set base_dir
|
||||||
|
set_fact:
|
||||||
|
base_dir: "{{ playbook_dir }}/.generated/"
|
||||||
|
|
||||||
|
- name: Create base_dir
|
||||||
|
file:
|
||||||
|
path: "{{ base_dir }}"
|
||||||
|
state: directory
|
||||||
|
recurse: true
|
||||||
|
mode: 0755
|
||||||
|
|
||||||
|
- name: Store json files in base_dir
|
||||||
|
template:
|
||||||
|
src: "{{ item }}"
|
||||||
|
dest: "{{ base_dir }}/{{ item }}"
|
||||||
|
mode: 0644
|
||||||
|
with_items:
|
||||||
|
- network.json
|
||||||
|
- storage.json
|
||||||
|
- availability-sets.json
|
||||||
|
- bastion.json
|
||||||
|
- masters.json
|
||||||
|
- minions.json
|
||||||
|
- clear-rg.json
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Compute/availabilitySets",
|
||||||
|
"name": "{{availabilitySetMasters}}",
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"PlatformFaultDomainCount": "{{faultDomainCount}}",
|
||||||
|
"PlatformUpdateDomainCount": "{{updateDomainCount}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Compute/availabilitySets",
|
||||||
|
"name": "{{availabilitySetMinions}}",
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"PlatformFaultDomainCount": "{{faultDomainCount}}",
|
||||||
|
"PlatformUpdateDomainCount": "{{updateDomainCount}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
106
contrib/azurerm/roles/generate-templates/templates/bastion.json
Normal file
106
contrib/azurerm/roles/generate-templates/templates/bastion.json
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks', '{{virtualNetworkName}}')]",
|
||||||
|
"subnetAdminRef": "[concat(variables('vnetID'),'/subnets/', '{{subnetAdminName}}')]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{% if use_bastion %}
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"type": "Microsoft.Network/publicIPAddresses",
|
||||||
|
"name": "{{bastionIPAddressName}}",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"publicIPAllocationMethod": "Static",
|
||||||
|
"dnsSettings": {
|
||||||
|
{% if bastion_domain_prefix %}
|
||||||
|
"domainNameLabel": "{{ bastion_domain_prefix }}"
|
||||||
|
{% endif %}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"type": "Microsoft.Network/networkInterfaces",
|
||||||
|
"name": "{{bastionVMName}}-nic",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"dependsOn": [
|
||||||
|
"[concat('Microsoft.Network/publicIPAddresses/', '{{bastionIPAddressName}}')]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"ipConfigurations": [
|
||||||
|
{
|
||||||
|
"name": "BastionIpConfig",
|
||||||
|
"properties": {
|
||||||
|
"privateIPAllocationMethod": "Dynamic",
|
||||||
|
"publicIPAddress": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/publicIPAddresses', '{{bastionIPAddressName}}')]"
|
||||||
|
},
|
||||||
|
"subnet": {
|
||||||
|
"id": "[variables('subnetAdminRef')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"type": "Microsoft.Compute/virtualMachines",
|
||||||
|
"name": "{{bastionVMName}}",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"dependsOn": [
|
||||||
|
"[concat('Microsoft.Network/networkInterfaces/', '{{bastionVMName}}-nic')]"
|
||||||
|
],
|
||||||
|
"tags": {
|
||||||
|
"roles": "bastion"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"hardwareProfile": {
|
||||||
|
"vmSize": "{{bastionVmSize}}"
|
||||||
|
},
|
||||||
|
"osProfile": {
|
||||||
|
"computerName": "{{bastionVMName}}",
|
||||||
|
"adminUsername": "{{admin_username}}",
|
||||||
|
"adminPassword": "{{admin_password}}",
|
||||||
|
"linuxConfiguration": {
|
||||||
|
"disablePasswordAuthentication": "true",
|
||||||
|
"ssh": {
|
||||||
|
"publicKeys": [
|
||||||
|
{% for key in ssh_public_keys %}
|
||||||
|
{
|
||||||
|
"path": "{{sshKeyPath}}",
|
||||||
|
"keyData": "{{key}}"
|
||||||
|
}{% if loop.index < ssh_public_keys | length %},{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"storageProfile": {
|
||||||
|
"imageReference": {{imageReferenceJson}},
|
||||||
|
"osDisk": {
|
||||||
|
"name": "osdisk",
|
||||||
|
"vhd": {
|
||||||
|
"uri": "[concat('http://', '{{storageAccountName}}', '.blob.core.windows.net/vhds/', '{{bastionVMName}}', '-osdisk.vhd')]"
|
||||||
|
},
|
||||||
|
"caching": "ReadWrite",
|
||||||
|
"createOption": "FromImage"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"networkProfile": {
|
||||||
|
"networkInterfaces": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkInterfaces', '{{bastionVMName}}-nic')]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {},
|
||||||
|
"variables": {},
|
||||||
|
"resources": [],
|
||||||
|
"outputs": {}
|
||||||
|
}
|
198
contrib/azurerm/roles/generate-templates/templates/masters.json
Normal file
198
contrib/azurerm/roles/generate-templates/templates/masters.json
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"lbDomainName": "{{nameSuffix}}-api",
|
||||||
|
"lbPublicIPAddressName": "kubernetes-api-pubip",
|
||||||
|
"lbPublicIPAddressType": "Static",
|
||||||
|
"lbPublicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('lbPublicIPAddressName'))]",
|
||||||
|
"lbName": "kubernetes-api",
|
||||||
|
"lbID": "[resourceId('Microsoft.Network/loadBalancers',variables('lbName'))]",
|
||||||
|
|
||||||
|
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks', '{{virtualNetworkName}}')]",
|
||||||
|
"kubeMastersSubnetRef": "[concat(variables('vnetID'),'/subnets/', '{{subnetMastersName}}')]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"type": "Microsoft.Network/publicIPAddresses",
|
||||||
|
"name": "[variables('lbPublicIPAddressName')]",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"publicIPAllocationMethod": "[variables('lbPublicIPAddressType')]",
|
||||||
|
"dnsSettings": {
|
||||||
|
"domainNameLabel": "[variables('lbDomainName')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"name": "[variables('lbName')]",
|
||||||
|
"type": "Microsoft.Network/loadBalancers",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"dependsOn": [
|
||||||
|
"[concat('Microsoft.Network/publicIPAddresses/', variables('lbPublicIPAddressName'))]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"frontendIPConfigurations": [
|
||||||
|
{
|
||||||
|
"name": "kube-api-frontend",
|
||||||
|
"properties": {
|
||||||
|
"publicIPAddress": {
|
||||||
|
"id": "[variables('lbPublicIPAddressID')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"backendAddressPools": [
|
||||||
|
{
|
||||||
|
"name": "kube-api-backend"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"loadBalancingRules": [
|
||||||
|
{
|
||||||
|
"name": "kube-api",
|
||||||
|
"properties": {
|
||||||
|
"frontendIPConfiguration": {
|
||||||
|
"id": "[concat(variables('lbID'), '/frontendIPConfigurations/kube-api-frontend')]"
|
||||||
|
},
|
||||||
|
"backendAddressPool": {
|
||||||
|
"id": "[concat(variables('lbID'), '/backendAddressPools/kube-api-backend')]"
|
||||||
|
},
|
||||||
|
"protocol": "tcp",
|
||||||
|
"frontendPort": "{{kube_apiserver_port}}",
|
||||||
|
"backendPort": "{{kube_apiserver_port}}",
|
||||||
|
"enableFloatingIP": false,
|
||||||
|
"idleTimeoutInMinutes": 5,
|
||||||
|
"probe": {
|
||||||
|
"id": "[concat(variables('lbID'), '/probes/kube-api')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"probes": [
|
||||||
|
{
|
||||||
|
"name": "kube-api",
|
||||||
|
"properties": {
|
||||||
|
"protocol": "tcp",
|
||||||
|
"port": "{{kube_apiserver_port}}",
|
||||||
|
"intervalInSeconds": 5,
|
||||||
|
"numberOfProbes": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{% for i in range(number_of_k8s_masters) %}
|
||||||
|
{% if not use_bastion %}
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"type": "Microsoft.Network/publicIPAddresses",
|
||||||
|
"name": "master-{{i}}-pubip",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"publicIPAllocationMethod": "Static"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{% endif %}
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"type": "Microsoft.Network/networkInterfaces",
|
||||||
|
"name": "master-{{i}}-nic",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"dependsOn": [
|
||||||
|
{% if not use_bastion %}
|
||||||
|
"[concat('Microsoft.Network/publicIPAddresses/', 'master-{{i}}-pubip')]",
|
||||||
|
{% endif %}
|
||||||
|
"[concat('Microsoft.Network/loadBalancers/', variables('lbName'))]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"ipConfigurations": [
|
||||||
|
{
|
||||||
|
"name": "MastersIpConfig",
|
||||||
|
"properties": {
|
||||||
|
"privateIPAllocationMethod": "Dynamic",
|
||||||
|
{% if not use_bastion %}
|
||||||
|
"publicIPAddress": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/publicIPAddresses', 'master-{{i}}-pubip')]"
|
||||||
|
},
|
||||||
|
{% endif %}
|
||||||
|
"subnet": {
|
||||||
|
"id": "[variables('kubeMastersSubnetRef')]"
|
||||||
|
},
|
||||||
|
"loadBalancerBackendAddressPools": [
|
||||||
|
{
|
||||||
|
"id": "[concat(variables('lbID'), '/backendAddressPools/kube-api-backend')]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"networkSecurityGroup": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', '{{securityGroupName}}')]"
|
||||||
|
},
|
||||||
|
"enableIPForwarding": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Compute/virtualMachines",
|
||||||
|
"name": "master-{{i}}",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"dependsOn": [
|
||||||
|
"[concat('Microsoft.Network/networkInterfaces/', 'master-{{i}}-nic')]"
|
||||||
|
],
|
||||||
|
"tags": {
|
||||||
|
"roles": "kube_control_plane,etcd"
|
||||||
|
},
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"properties": {
|
||||||
|
"availabilitySet": {
|
||||||
|
"id": "[resourceId('Microsoft.Compute/availabilitySets', '{{availabilitySetMasters}}')]"
|
||||||
|
},
|
||||||
|
"hardwareProfile": {
|
||||||
|
"vmSize": "{{masters_vm_size}}"
|
||||||
|
},
|
||||||
|
"osProfile": {
|
||||||
|
"computerName": "master-{{i}}",
|
||||||
|
"adminUsername": "{{admin_username}}",
|
||||||
|
"adminPassword": "{{admin_password}}",
|
||||||
|
"linuxConfiguration": {
|
||||||
|
"disablePasswordAuthentication": "{{disablePasswordAuthentication}}",
|
||||||
|
"ssh": {
|
||||||
|
"publicKeys": [
|
||||||
|
{% for key in ssh_public_keys %}
|
||||||
|
{
|
||||||
|
"path": "{{sshKeyPath}}",
|
||||||
|
"keyData": "{{key}}"
|
||||||
|
}{% if loop.index < ssh_public_keys | length %},{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"storageProfile": {
|
||||||
|
"imageReference": {{imageReferenceJson}},
|
||||||
|
"osDisk": {
|
||||||
|
"name": "ma{{nameSuffix}}{{i}}",
|
||||||
|
"vhd": {
|
||||||
|
"uri": "[concat('http://','{{storageAccountName}}','.blob.core.windows.net/vhds/master-{{i}}.vhd')]"
|
||||||
|
},
|
||||||
|
"caching": "ReadWrite",
|
||||||
|
"createOption": "FromImage",
|
||||||
|
"diskSizeGB": "{{masters_os_disk_size}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"networkProfile": {
|
||||||
|
"networkInterfaces": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkInterfaces', 'master-{{i}}-nic')]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} {% if not loop.last %},{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
]
|
||||||
|
}
|
115
contrib/azurerm/roles/generate-templates/templates/minions.json
Normal file
115
contrib/azurerm/roles/generate-templates/templates/minions.json
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks', '{{virtualNetworkName}}')]",
|
||||||
|
"kubeMinionsSubnetRef": "[concat(variables('vnetID'),'/subnets/', '{{subnetMinionsName}}')]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{% for i in range(number_of_k8s_nodes) %}
|
||||||
|
{% if not use_bastion %}
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"type": "Microsoft.Network/publicIPAddresses",
|
||||||
|
"name": "minion-{{i}}-pubip",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"publicIPAllocationMethod": "Static"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{% endif %}
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"type": "Microsoft.Network/networkInterfaces",
|
||||||
|
"name": "minion-{{i}}-nic",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"dependsOn": [
|
||||||
|
{% if not use_bastion %}
|
||||||
|
"[concat('Microsoft.Network/publicIPAddresses/', 'minion-{{i}}-pubip')]"
|
||||||
|
{% endif %}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"ipConfigurations": [
|
||||||
|
{
|
||||||
|
"name": "MinionsIpConfig",
|
||||||
|
"properties": {
|
||||||
|
"privateIPAllocationMethod": "Dynamic",
|
||||||
|
{% if not use_bastion %}
|
||||||
|
"publicIPAddress": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/publicIPAddresses', 'minion-{{i}}-pubip')]"
|
||||||
|
},
|
||||||
|
{% endif %}
|
||||||
|
"subnet": {
|
||||||
|
"id": "[variables('kubeMinionsSubnetRef')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"networkSecurityGroup": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', '{{securityGroupName}}')]"
|
||||||
|
},
|
||||||
|
"enableIPForwarding": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Compute/virtualMachines",
|
||||||
|
"name": "minion-{{i}}",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"dependsOn": [
|
||||||
|
"[concat('Microsoft.Network/networkInterfaces/', 'minion-{{i}}-nic')]"
|
||||||
|
],
|
||||||
|
"tags": {
|
||||||
|
"roles": "kube_node"
|
||||||
|
},
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"properties": {
|
||||||
|
"availabilitySet": {
|
||||||
|
"id": "[resourceId('Microsoft.Compute/availabilitySets', '{{availabilitySetMinions}}')]"
|
||||||
|
},
|
||||||
|
"hardwareProfile": {
|
||||||
|
"vmSize": "{{minions_vm_size}}"
|
||||||
|
},
|
||||||
|
"osProfile": {
|
||||||
|
"computerName": "minion-{{i}}",
|
||||||
|
"adminUsername": "{{admin_username}}",
|
||||||
|
"adminPassword": "{{admin_password}}",
|
||||||
|
"linuxConfiguration": {
|
||||||
|
"disablePasswordAuthentication": "{{disablePasswordAuthentication}}",
|
||||||
|
"ssh": {
|
||||||
|
"publicKeys": [
|
||||||
|
{% for key in ssh_public_keys %}
|
||||||
|
{
|
||||||
|
"path": "{{sshKeyPath}}",
|
||||||
|
"keyData": "{{key}}"
|
||||||
|
}{% if loop.index < ssh_public_keys | length %},{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"storageProfile": {
|
||||||
|
"imageReference": {{imageReferenceJson}},
|
||||||
|
"osDisk": {
|
||||||
|
"name": "mi{{nameSuffix}}{{i}}",
|
||||||
|
"vhd": {
|
||||||
|
"uri": "[concat('http://','{{storageAccountName}}','.blob.core.windows.net/vhds/minion-{{i}}.vhd')]"
|
||||||
|
},
|
||||||
|
"caching": "ReadWrite",
|
||||||
|
"createOption": "FromImage",
|
||||||
|
"diskSizeGB": "{{minions_os_disk_size}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"networkProfile": {
|
||||||
|
"networkInterfaces": [
|
||||||
|
{
|
||||||
|
"id": "[resourceId('Microsoft.Network/networkInterfaces', 'minion-{{i}}-nic')]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} {% if not loop.last %},{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
]
|
||||||
|
}
|
109
contrib/azurerm/roles/generate-templates/templates/network.json
Normal file
109
contrib/azurerm/roles/generate-templates/templates/network.json
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"type": "Microsoft.Network/routeTables",
|
||||||
|
"name": "{{routeTableName}}",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"routes": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Network/virtualNetworks",
|
||||||
|
"name": "{{virtualNetworkName}}",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"dependsOn": [
|
||||||
|
"[concat('Microsoft.Network/routeTables/', '{{routeTableName}}')]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"addressSpace": {
|
||||||
|
"addressPrefixes": [
|
||||||
|
"{{azure_vnet_cidr}}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"subnets": [
|
||||||
|
{
|
||||||
|
"name": "{{subnetMastersName}}",
|
||||||
|
"properties": {
|
||||||
|
"addressPrefix": "{{azure_masters_cidr}}",
|
||||||
|
"routeTable": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/routeTables', '{{routeTableName}}')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "{{subnetMinionsName}}",
|
||||||
|
"properties": {
|
||||||
|
"addressPrefix": "{{azure_minions_cidr}}",
|
||||||
|
"routeTable": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/routeTables', '{{routeTableName}}')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{% if use_bastion %}
|
||||||
|
,{
|
||||||
|
"name": "{{subnetAdminName}}",
|
||||||
|
"properties": {
|
||||||
|
"addressPrefix": "{{azure_admin_cidr}}",
|
||||||
|
"routeTable": {
|
||||||
|
"id": "[resourceId('Microsoft.Network/routeTables', '{{routeTableName}}')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"type": "Microsoft.Network/networkSecurityGroups",
|
||||||
|
"name": "{{securityGroupName}}",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"properties": {
|
||||||
|
"securityRules": [
|
||||||
|
{% if not use_bastion %}
|
||||||
|
{
|
||||||
|
"name": "ssh",
|
||||||
|
"properties": {
|
||||||
|
"description": "Allow SSH",
|
||||||
|
"protocol": "Tcp",
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationPortRange": "22",
|
||||||
|
"sourceAddressPrefix": "Internet",
|
||||||
|
"destinationAddressPrefix": "*",
|
||||||
|
"access": "Allow",
|
||||||
|
"priority": 100,
|
||||||
|
"direction": "Inbound"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{% endif %}
|
||||||
|
{
|
||||||
|
"name": "kube-api",
|
||||||
|
"properties": {
|
||||||
|
"description": "Allow secure kube-api",
|
||||||
|
"protocol": "Tcp",
|
||||||
|
"sourcePortRange": "*",
|
||||||
|
"destinationPortRange": "{{kube_apiserver_port}}",
|
||||||
|
"sourceAddressPrefix": "Internet",
|
||||||
|
"destinationAddressPrefix": "*",
|
||||||
|
"access": "Allow",
|
||||||
|
"priority": 101,
|
||||||
|
"direction": "Inbound"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"resources": [],
|
||||||
|
"dependsOn": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Storage/storageAccounts",
|
||||||
|
"name": "{{storageAccountName}}",
|
||||||
|
"location": "[resourceGroup().location]",
|
||||||
|
"apiVersion": "{{apiVersion}}",
|
||||||
|
"properties": {
|
||||||
|
"accountType": "{{storageAccountType}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
177
contrib/dind/README.md
Normal file
177
contrib/dind/README.md
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
# Kubespray DIND experimental setup
|
||||||
|
|
||||||
|
This ansible playbook creates local docker containers
|
||||||
|
to serve as Kubernetes "nodes", which in turn will run
|
||||||
|
"normal" Kubernetes docker containers, a mode usually
|
||||||
|
called DIND (Docker-IN-Docker).
|
||||||
|
|
||||||
|
The playbook has two roles:
|
||||||
|
|
||||||
|
- dind-host: creates the "nodes" as containers in localhost, with
|
||||||
|
appropriate settings for DIND (privileged, volume mapping for dind
|
||||||
|
storage, etc).
|
||||||
|
- dind-cluster: customizes each node container to have required
|
||||||
|
system packages installed, and some utils (swapoff, lsattr)
|
||||||
|
symlinked to /bin/true to ease mimicking a real node.
|
||||||
|
|
||||||
|
This playbook has been test with Ubuntu 16.04 as host and ubuntu:16.04
|
||||||
|
as docker images (note that dind-cluster has specific customization
|
||||||
|
for these images).
|
||||||
|
|
||||||
|
The playbook also creates a `/tmp/kubespray.dind.inventory_builder.sh`
|
||||||
|
helper (wraps up running `contrib/inventory_builder/inventory.py` with
|
||||||
|
node containers IPs and prefix).
|
||||||
|
|
||||||
|
## Deploying
|
||||||
|
|
||||||
|
See below for a complete successful run:
|
||||||
|
|
||||||
|
1. Create the node containers
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# From the kubespray root dir
|
||||||
|
cd contrib/dind
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
ansible-playbook -i hosts dind-cluster.yaml
|
||||||
|
|
||||||
|
# Back to kubespray root
|
||||||
|
cd ../..
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: if the playbook run fails with something like below error
|
||||||
|
message, you may need to specifically set `ansible_python_interpreter`,
|
||||||
|
see `./hosts` file for an example expanded localhost entry.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
failed: [localhost] (item=kube-node1) => {"changed": false, "item": "kube-node1", "msg": "Failed to import docker or docker-py - No module named requests.exceptions. Try `pip install docker` or `pip install docker-py` (Python 2.6)"}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Customize kubespray-dind.yaml
|
||||||
|
|
||||||
|
Note that there's coupling between above created node containers
|
||||||
|
and `kubespray-dind.yaml` settings, in particular regarding selected `node_distro`
|
||||||
|
(as set in `group_vars/all/all.yaml`), and docker settings.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$EDITOR contrib/dind/kubespray-dind.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Prepare the inventory and run the playbook
|
||||||
|
|
||||||
|
```shell
|
||||||
|
INVENTORY_DIR=inventory/local-dind
|
||||||
|
mkdir -p ${INVENTORY_DIR}
|
||||||
|
rm -f ${INVENTORY_DIR}/hosts.ini
|
||||||
|
CONFIG_FILE=${INVENTORY_DIR}/hosts.ini /tmp/kubespray.dind.inventory_builder.sh
|
||||||
|
|
||||||
|
ansible-playbook --become -e ansible_ssh_user=debian -i ${INVENTORY_DIR}/hosts.ini cluster.yml --extra-vars @contrib/dind/kubespray-dind.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: You could also test other distros without editing files by
|
||||||
|
passing `--extra-vars` as per below commandline,
|
||||||
|
replacing `DISTRO` by either `debian`, `ubuntu`, `centos`, `fedora`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cd contrib/dind
|
||||||
|
ansible-playbook -i hosts dind-cluster.yaml --extra-vars node_distro=DISTRO
|
||||||
|
|
||||||
|
cd ../..
|
||||||
|
CONFIG_FILE=inventory/local-dind/hosts.ini /tmp/kubespray.dind.inventory_builder.sh
|
||||||
|
ansible-playbook --become -e ansible_ssh_user=DISTRO -i inventory/local-dind/hosts.ini cluster.yml --extra-vars @contrib/dind/kubespray-dind.yaml --extra-vars bootstrap_os=DISTRO
|
||||||
|
```
|
||||||
|
|
||||||
|
## Resulting deployment
|
||||||
|
|
||||||
|
See below to get an idea on how a completed deployment looks like,
|
||||||
|
from the host where you ran kubespray playbooks.
|
||||||
|
|
||||||
|
### node_distro: debian
|
||||||
|
|
||||||
|
Running from an Ubuntu Xenial host:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ uname -a
|
||||||
|
Linux ip-xx-xx-xx-xx 4.4.0-1069-aws #79-Ubuntu SMP Mon Sep 24
|
||||||
|
15:01:41 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
|
||||||
|
|
||||||
|
$ docker ps
|
||||||
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
|
1835dd183b75 debian:9.5 "sh -c 'apt-get -qy …" 43 minutes ago Up 43 minutes kube-node5
|
||||||
|
30b0af8d2924 debian:9.5 "sh -c 'apt-get -qy …" 43 minutes ago Up 43 minutes kube-node4
|
||||||
|
3e0d1510c62f debian:9.5 "sh -c 'apt-get -qy …" 43 minutes ago Up 43 minutes kube-node3
|
||||||
|
738993566f94 debian:9.5 "sh -c 'apt-get -qy …" 44 minutes ago Up 44 minutes kube-node2
|
||||||
|
c581ef662ed2 debian:9.5 "sh -c 'apt-get -qy …" 44 minutes ago Up 44 minutes kube-node1
|
||||||
|
|
||||||
|
$ docker exec kube-node1 kubectl get node
|
||||||
|
NAME STATUS ROLES AGE VERSION
|
||||||
|
kube-node1 Ready master,node 18m v1.12.1
|
||||||
|
kube-node2 Ready master,node 17m v1.12.1
|
||||||
|
kube-node3 Ready node 17m v1.12.1
|
||||||
|
kube-node4 Ready node 17m v1.12.1
|
||||||
|
kube-node5 Ready node 17m v1.12.1
|
||||||
|
|
||||||
|
$ docker exec kube-node1 kubectl get pod --all-namespaces
|
||||||
|
NAMESPACE NAME READY STATUS RESTARTS AGE
|
||||||
|
default netchecker-agent-67489 1/1 Running 0 2m51s
|
||||||
|
default netchecker-agent-6qq6s 1/1 Running 0 2m51s
|
||||||
|
default netchecker-agent-fsw92 1/1 Running 0 2m51s
|
||||||
|
default netchecker-agent-fw6tl 1/1 Running 0 2m51s
|
||||||
|
default netchecker-agent-hostnet-8f2zb 1/1 Running 0 3m
|
||||||
|
default netchecker-agent-hostnet-gq7ml 1/1 Running 0 3m
|
||||||
|
default netchecker-agent-hostnet-jfkgv 1/1 Running 0 3m
|
||||||
|
default netchecker-agent-hostnet-kwfwx 1/1 Running 0 3m
|
||||||
|
default netchecker-agent-hostnet-r46nm 1/1 Running 0 3m
|
||||||
|
default netchecker-agent-lxdrn 1/1 Running 0 2m51s
|
||||||
|
default netchecker-server-864bd4c897-9vstl 1/1 Running 0 2m40s
|
||||||
|
default sh-68fcc6db45-qf55h 1/1 Running 1 12m
|
||||||
|
kube-system coredns-7598f59475-6vknq 1/1 Running 0 14m
|
||||||
|
kube-system coredns-7598f59475-l5q5x 1/1 Running 0 14m
|
||||||
|
kube-system kube-apiserver-kube-node1 1/1 Running 0 17m
|
||||||
|
kube-system kube-apiserver-kube-node2 1/1 Running 0 18m
|
||||||
|
kube-system kube-controller-manager-kube-node1 1/1 Running 0 18m
|
||||||
|
kube-system kube-controller-manager-kube-node2 1/1 Running 0 18m
|
||||||
|
kube-system kube-proxy-5xx9d 1/1 Running 0 17m
|
||||||
|
kube-system kube-proxy-cdqq4 1/1 Running 0 17m
|
||||||
|
kube-system kube-proxy-n64ls 1/1 Running 0 17m
|
||||||
|
kube-system kube-proxy-pswmj 1/1 Running 0 18m
|
||||||
|
kube-system kube-proxy-x89qw 1/1 Running 0 18m
|
||||||
|
kube-system kube-scheduler-kube-node1 1/1 Running 4 17m
|
||||||
|
kube-system kube-scheduler-kube-node2 1/1 Running 4 18m
|
||||||
|
kube-system kubernetes-dashboard-5db4d9f45f-548rl 1/1 Running 0 14m
|
||||||
|
kube-system nginx-proxy-kube-node3 1/1 Running 4 17m
|
||||||
|
kube-system nginx-proxy-kube-node4 1/1 Running 4 17m
|
||||||
|
kube-system nginx-proxy-kube-node5 1/1 Running 4 17m
|
||||||
|
kube-system weave-net-42bfr 2/2 Running 0 16m
|
||||||
|
kube-system weave-net-6gt8m 2/2 Running 0 16m
|
||||||
|
kube-system weave-net-88nnc 2/2 Running 0 16m
|
||||||
|
kube-system weave-net-shckr 2/2 Running 0 16m
|
||||||
|
kube-system weave-net-xr46t 2/2 Running 0 16m
|
||||||
|
|
||||||
|
$ docker exec kube-node1 curl -s http://localhost:31081/api/v1/connectivity_check
|
||||||
|
{"Message":"All 10 pods successfully reported back to the server","Absent":null,"Outdated":null}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using ./run-test-distros.sh
|
||||||
|
|
||||||
|
You can use `./run-test-distros.sh` to run a set of tests via DIND,
|
||||||
|
and excerpt from this script, to get an idea:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# The SPEC file(s) must have two arrays as e.g.
|
||||||
|
# DISTROS=(debian centos)
|
||||||
|
# EXTRAS=(
|
||||||
|
# 'kube_network_plugin=calico'
|
||||||
|
# 'kube_network_plugin=flannel'
|
||||||
|
# 'kube_network_plugin=weave'
|
||||||
|
# )
|
||||||
|
# that will be tested in a "combinatory" way (e.g. from above there'll be
|
||||||
|
# be 6 test runs), creating a sequenced <spec_filename>-nn.out with each output.
|
||||||
|
#
|
||||||
|
# Each $EXTRAS element will be whitespace split, and passed as --extra-vars
|
||||||
|
# to main kubespray ansible-playbook run.
|
||||||
|
```
|
||||||
|
|
||||||
|
See e.g. `test-some_distros-most_CNIs.env` and
|
||||||
|
`test-some_distros-kube_router_combo.env` in particular for a richer
|
||||||
|
set of CNI specific `--extra-vars` combo.
|
9
contrib/dind/dind-cluster.yaml
Normal file
9
contrib/dind/dind-cluster.yaml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
gather_facts: False
|
||||||
|
roles:
|
||||||
|
- { role: dind-host }
|
||||||
|
|
||||||
|
- hosts: containers
|
||||||
|
roles:
|
||||||
|
- { role: dind-cluster }
|
3
contrib/dind/group_vars/all/all.yaml
Normal file
3
contrib/dind/group_vars/all/all.yaml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
# See distro.yaml for supported node_distro images
|
||||||
|
node_distro: debian
|
41
contrib/dind/group_vars/all/distro.yaml
Normal file
41
contrib/dind/group_vars/all/distro.yaml
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
distro_settings:
|
||||||
|
debian: &DEBIAN
|
||||||
|
image: "debian:9.5"
|
||||||
|
user: "debian"
|
||||||
|
pid1_exe: /lib/systemd/systemd
|
||||||
|
init: |
|
||||||
|
sh -c "apt-get -qy update && apt-get -qy install systemd-sysv dbus && exec /sbin/init"
|
||||||
|
raw_setup: apt-get -qy update && apt-get -qy install dbus python sudo iproute2
|
||||||
|
raw_setup_done: test -x /usr/bin/sudo
|
||||||
|
agetty_svc: getty@*
|
||||||
|
ssh_service: ssh
|
||||||
|
extra_packages: []
|
||||||
|
ubuntu:
|
||||||
|
<<: *DEBIAN
|
||||||
|
image: "ubuntu:16.04"
|
||||||
|
user: "ubuntu"
|
||||||
|
init: |
|
||||||
|
/sbin/init
|
||||||
|
centos: &CENTOS
|
||||||
|
image: "centos:7"
|
||||||
|
user: "centos"
|
||||||
|
pid1_exe: /usr/lib/systemd/systemd
|
||||||
|
init: |
|
||||||
|
/sbin/init
|
||||||
|
raw_setup: yum -qy install policycoreutils dbus python sudo iproute iptables
|
||||||
|
raw_setup_done: test -x /usr/bin/sudo
|
||||||
|
agetty_svc: getty@* serial-getty@*
|
||||||
|
ssh_service: sshd
|
||||||
|
extra_packages: []
|
||||||
|
fedora:
|
||||||
|
<<: *CENTOS
|
||||||
|
image: "fedora:latest"
|
||||||
|
user: "fedora"
|
||||||
|
raw_setup: yum -qy install policycoreutils dbus python sudo iproute iptables; mkdir -p /etc/modules-load.d
|
||||||
|
extra_packages:
|
||||||
|
- hostname
|
||||||
|
- procps
|
||||||
|
- findutils
|
||||||
|
- kmod
|
||||||
|
- iputils
|
15
contrib/dind/hosts
Normal file
15
contrib/dind/hosts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[local]
|
||||||
|
# If you created a virtualenv for ansible, you may need to specify running the
|
||||||
|
# python binary from there instead:
|
||||||
|
#localhost ansible_connection=local ansible_python_interpreter=/home/user/kubespray/.venv/bin/python
|
||||||
|
localhost ansible_connection=local
|
||||||
|
|
||||||
|
[containers]
|
||||||
|
kube-node1
|
||||||
|
kube-node2
|
||||||
|
kube-node3
|
||||||
|
kube-node4
|
||||||
|
kube-node5
|
||||||
|
|
||||||
|
[containers:vars]
|
||||||
|
ansible_connection=docker
|
22
contrib/dind/kubespray-dind.yaml
Normal file
22
contrib/dind/kubespray-dind.yaml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
# kubespray-dind.yaml: minimal kubespray ansible playbook usable for DIND
|
||||||
|
# See contrib/dind/README.md
|
||||||
|
kube_api_anonymous_auth: true
|
||||||
|
|
||||||
|
kubelet_fail_swap_on: false
|
||||||
|
|
||||||
|
# Docker nodes need to have been created with same "node_distro: debian"
|
||||||
|
# at contrib/dind/group_vars/all/all.yaml
|
||||||
|
bootstrap_os: debian
|
||||||
|
|
||||||
|
docker_version: latest
|
||||||
|
|
||||||
|
docker_storage_options: -s overlay2 --storage-opt overlay2.override_kernel_check=true -g /dind/docker
|
||||||
|
|
||||||
|
dns_mode: coredns
|
||||||
|
|
||||||
|
deploy_netchecker: True
|
||||||
|
netcheck_agent_image_repo: quay.io/l23network/k8s-netchecker-agent
|
||||||
|
netcheck_server_image_repo: quay.io/l23network/k8s-netchecker-server
|
||||||
|
netcheck_agent_image_tag: v1.0
|
||||||
|
netcheck_server_image_tag: v1.0
|
1
contrib/dind/requirements.txt
Normal file
1
contrib/dind/requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
docker
|
73
contrib/dind/roles/dind-cluster/tasks/main.yaml
Normal file
73
contrib/dind/roles/dind-cluster/tasks/main.yaml
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
---
|
||||||
|
- name: set_fact distro_setup
|
||||||
|
set_fact:
|
||||||
|
distro_setup: "{{ distro_settings[node_distro] }}"
|
||||||
|
|
||||||
|
- name: set_fact other distro settings
|
||||||
|
set_fact:
|
||||||
|
distro_user: "{{ distro_setup['user'] }}"
|
||||||
|
distro_ssh_service: "{{ distro_setup['ssh_service'] }}"
|
||||||
|
distro_extra_packages: "{{ distro_setup['extra_packages'] }}"
|
||||||
|
|
||||||
|
- name: Null-ify some linux tools to ease DIND
|
||||||
|
file:
|
||||||
|
src: "/bin/true"
|
||||||
|
dest: "{{ item }}"
|
||||||
|
state: link
|
||||||
|
force: yes
|
||||||
|
with_items:
|
||||||
|
# DIND box may have swap enable, don't bother
|
||||||
|
- /sbin/swapoff
|
||||||
|
# /etc/hosts handling would fail on trying to copy file attributes on edit,
|
||||||
|
# void it by successfully returning nil output
|
||||||
|
- /usr/bin/lsattr
|
||||||
|
# disable selinux-isms, sp needed if running on non-Selinux host
|
||||||
|
- /usr/sbin/semodule
|
||||||
|
|
||||||
|
- name: Void installing dpkg docs and man pages on Debian based distros
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
# Delete locales
|
||||||
|
path-exclude=/usr/share/locale/*
|
||||||
|
# Delete man pages
|
||||||
|
path-exclude=/usr/share/man/*
|
||||||
|
# Delete docs
|
||||||
|
path-exclude=/usr/share/doc/*
|
||||||
|
path-include=/usr/share/doc/*/copyright
|
||||||
|
dest: /etc/dpkg/dpkg.cfg.d/01_nodoc
|
||||||
|
mode: 0644
|
||||||
|
when:
|
||||||
|
- ansible_os_family == 'Debian'
|
||||||
|
|
||||||
|
- name: Install system packages to better match a full-fledge node
|
||||||
|
package:
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: present
|
||||||
|
with_items: "{{ distro_extra_packages }} + [ 'rsyslog', 'openssh-server' ]"
|
||||||
|
|
||||||
|
- name: Start needed services
|
||||||
|
service:
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: started
|
||||||
|
with_items:
|
||||||
|
- rsyslog
|
||||||
|
- "{{ distro_ssh_service }}"
|
||||||
|
|
||||||
|
- name: Create distro user "{{ distro_user }}"
|
||||||
|
user:
|
||||||
|
name: "{{ distro_user }}"
|
||||||
|
uid: 1000
|
||||||
|
# groups: sudo
|
||||||
|
append: yes
|
||||||
|
|
||||||
|
- name: Allow password-less sudo to "{{ distro_user }}"
|
||||||
|
copy:
|
||||||
|
content: "{{ distro_user }} ALL=(ALL) NOPASSWD:ALL"
|
||||||
|
dest: "/etc/sudoers.d/{{ distro_user }}"
|
||||||
|
mode: 0640
|
||||||
|
|
||||||
|
- name: Add my pubkey to "{{ distro_user }}" user authorized keys
|
||||||
|
authorized_key:
|
||||||
|
user: "{{ distro_user }}"
|
||||||
|
state: present
|
||||||
|
key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"
|
88
contrib/dind/roles/dind-host/tasks/main.yaml
Normal file
88
contrib/dind/roles/dind-host/tasks/main.yaml
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
---
|
||||||
|
- name: set_fact distro_setup
|
||||||
|
set_fact:
|
||||||
|
distro_setup: "{{ distro_settings[node_distro] }}"
|
||||||
|
|
||||||
|
- name: set_fact other distro settings
|
||||||
|
set_fact:
|
||||||
|
distro_image: "{{ distro_setup['image'] }}"
|
||||||
|
distro_init: "{{ distro_setup['init'] }}"
|
||||||
|
distro_pid1_exe: "{{ distro_setup['pid1_exe'] }}"
|
||||||
|
distro_raw_setup: "{{ distro_setup['raw_setup'] }}"
|
||||||
|
distro_raw_setup_done: "{{ distro_setup['raw_setup_done'] }}"
|
||||||
|
distro_agetty_svc: "{{ distro_setup['agetty_svc'] }}"
|
||||||
|
|
||||||
|
- name: Create dind node containers from "containers" inventory section
|
||||||
|
docker_container:
|
||||||
|
image: "{{ distro_image }}"
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: started
|
||||||
|
hostname: "{{ item }}"
|
||||||
|
command: "{{ distro_init }}"
|
||||||
|
# recreate: yes
|
||||||
|
privileged: true
|
||||||
|
tmpfs:
|
||||||
|
- /sys/module/nf_conntrack/parameters
|
||||||
|
volumes:
|
||||||
|
- /boot:/boot
|
||||||
|
- /lib/modules:/lib/modules
|
||||||
|
- "{{ item }}:/dind/docker"
|
||||||
|
register: containers
|
||||||
|
with_items: "{{ groups.containers }}"
|
||||||
|
tags:
|
||||||
|
- addresses
|
||||||
|
|
||||||
|
- name: Gather list of containers IPs
|
||||||
|
set_fact:
|
||||||
|
addresses: "{{ containers.results | map(attribute='ansible_facts') | map(attribute='docker_container') | map(attribute='NetworkSettings') | map(attribute='IPAddress') | list }}"
|
||||||
|
tags:
|
||||||
|
- addresses
|
||||||
|
|
||||||
|
- name: Create inventory_builder helper already set with the list of node containers' IPs
|
||||||
|
template:
|
||||||
|
src: inventory_builder.sh.j2
|
||||||
|
dest: /tmp/kubespray.dind.inventory_builder.sh
|
||||||
|
mode: 0755
|
||||||
|
tags:
|
||||||
|
- addresses
|
||||||
|
|
||||||
|
- name: Install needed packages into node containers via raw, need to wait for possible systemd packages to finish installing
|
||||||
|
raw: |
|
||||||
|
# agetty processes churn a lot of cpu time failing on inexistent ttys, early STOP them, to rip them in below task
|
||||||
|
pkill -STOP agetty || true
|
||||||
|
{{ distro_raw_setup_done }} && echo SKIPPED && exit 0
|
||||||
|
until [ "$(readlink /proc/1/exe)" = "{{ distro_pid1_exe }}" ] ; do sleep 1; done
|
||||||
|
{{ distro_raw_setup }}
|
||||||
|
delegate_to: "{{ item._ansible_item_label|default(item.item) }}"
|
||||||
|
with_items: "{{ containers.results }}"
|
||||||
|
register: result
|
||||||
|
changed_when: result.stdout.find("SKIPPED") < 0
|
||||||
|
|
||||||
|
- name: Remove gettys from node containers
|
||||||
|
raw: |
|
||||||
|
until test -S /var/run/dbus/system_bus_socket; do sleep 1; done
|
||||||
|
systemctl disable {{ distro_agetty_svc }}
|
||||||
|
systemctl stop {{ distro_agetty_svc }}
|
||||||
|
delegate_to: "{{ item._ansible_item_label|default(item.item) }}"
|
||||||
|
with_items: "{{ containers.results }}"
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
# Running systemd-machine-id-setup doesn't create a unique id for each node container on Debian,
|
||||||
|
# handle manually
|
||||||
|
- name: Re-create unique machine-id (as we may just get what comes in the docker image), needed by some CNIs for mac address seeding (notably weave) # noqa 301
|
||||||
|
raw: |
|
||||||
|
echo {{ item | hash('sha1') }} > /etc/machine-id.new
|
||||||
|
mv -b /etc/machine-id.new /etc/machine-id
|
||||||
|
cmp /etc/machine-id /etc/machine-id~ || true
|
||||||
|
systemctl daemon-reload
|
||||||
|
delegate_to: "{{ item._ansible_item_label|default(item.item) }}"
|
||||||
|
with_items: "{{ containers.results }}"
|
||||||
|
|
||||||
|
- name: Early hack image install to adapt for DIND
|
||||||
|
# noqa 302 - this task uses the raw module intentionally
|
||||||
|
raw: |
|
||||||
|
rm -fv /usr/bin/udevadm /usr/sbin/udevadm
|
||||||
|
delegate_to: "{{ item._ansible_item_label|default(item.item) }}"
|
||||||
|
with_items: "{{ containers.results }}"
|
||||||
|
register: result
|
||||||
|
changed_when: result.stdout.find("removed") >= 0
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# NOTE: if you change HOST_PREFIX, you also need to edit ./hosts [containers] section
|
||||||
|
HOST_PREFIX=kube-node python3 contrib/inventory_builder/inventory.py {% for ip in addresses %} {{ ip }} {% endfor %}
|
93
contrib/dind/run-test-distros.sh
Executable file
93
contrib/dind/run-test-distros.sh
Executable file
|
@ -0,0 +1,93 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Q&D test'em all: creates full DIND kubespray deploys
|
||||||
|
# for each distro, verifying it via netchecker.
|
||||||
|
|
||||||
|
info() {
|
||||||
|
local msg="$*"
|
||||||
|
local date="$(date -Isec)"
|
||||||
|
echo "INFO: [$date] $msg"
|
||||||
|
}
|
||||||
|
pass_or_fail() {
|
||||||
|
local rc="$?"
|
||||||
|
local msg="$*"
|
||||||
|
local date="$(date -Isec)"
|
||||||
|
[ $rc -eq 0 ] && echo "PASS: [$date] $msg" || echo "FAIL: [$date] $msg"
|
||||||
|
return $rc
|
||||||
|
}
|
||||||
|
test_distro() {
|
||||||
|
local distro=${1:?};shift
|
||||||
|
local extra="${*:-}"
|
||||||
|
local prefix="${distro[${extra}]}"
|
||||||
|
ansible-playbook -i hosts dind-cluster.yaml -e node_distro=$distro
|
||||||
|
pass_or_fail "$prefix: dind-nodes" || return 1
|
||||||
|
(cd ../..
|
||||||
|
INVENTORY_DIR=inventory/local-dind
|
||||||
|
mkdir -p ${INVENTORY_DIR}
|
||||||
|
rm -f ${INVENTORY_DIR}/hosts.ini
|
||||||
|
CONFIG_FILE=${INVENTORY_DIR}/hosts.ini /tmp/kubespray.dind.inventory_builder.sh
|
||||||
|
# expand $extra with -e in front of each word
|
||||||
|
extra_args=""; for extra_arg in $extra; do extra_args="$extra_args -e $extra_arg"; done
|
||||||
|
ansible-playbook --become -e ansible_ssh_user=$distro -i \
|
||||||
|
${INVENTORY_DIR}/hosts.ini cluster.yml \
|
||||||
|
-e @contrib/dind/kubespray-dind.yaml -e bootstrap_os=$distro ${extra_args}
|
||||||
|
pass_or_fail "$prefix: kubespray"
|
||||||
|
) || return 1
|
||||||
|
local node0=${NODES[0]}
|
||||||
|
docker exec ${node0} kubectl get pod --all-namespaces
|
||||||
|
pass_or_fail "$prefix: kube-api" || return 1
|
||||||
|
let retries=60
|
||||||
|
while ((retries--)); do
|
||||||
|
# Some CNI may set NodePort on "main" node interface address (thus no localhost NodePort)
|
||||||
|
# e.g. kube-router: https://github.com/cloudnativelabs/kube-router/pull/217
|
||||||
|
docker exec ${node0} curl -m2 -s http://${NETCHECKER_HOST:?}:31081/api/v1/connectivity_check | grep successfully && break
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
[ $retries -ge 0 ]
|
||||||
|
pass_or_fail "$prefix: netcheck" || return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
NODES=($(egrep ^kube_node hosts))
|
||||||
|
NETCHECKER_HOST=localhost
|
||||||
|
|
||||||
|
: ${OUTPUT_DIR:=./out}
|
||||||
|
mkdir -p ${OUTPUT_DIR}
|
||||||
|
|
||||||
|
# The SPEC file(s) must have two arrays as e.g.
|
||||||
|
# DISTROS=(debian centos)
|
||||||
|
# EXTRAS=(
|
||||||
|
# 'kube_network_plugin=calico'
|
||||||
|
# 'kube_network_plugin=flannel'
|
||||||
|
# 'kube_network_plugin=weave'
|
||||||
|
# )
|
||||||
|
# that will be tested in a "combinatory" way (e.g. from above there'll be
|
||||||
|
# be 6 test runs), creating a sequenced <spec_filename>-nn.out with each output.
|
||||||
|
#
|
||||||
|
# Each $EXTRAS element will be whitespace split, and passed as --extra-vars
|
||||||
|
# to main kubespray ansible-playbook run.
|
||||||
|
|
||||||
|
SPECS=${*:?Missing SPEC files, e.g. test-most_distros-some_CNIs.env}
|
||||||
|
for spec in ${SPECS}; do
|
||||||
|
unset DISTROS EXTRAS
|
||||||
|
echo "Loading file=${spec} ..."
|
||||||
|
. ${spec} || continue
|
||||||
|
: ${DISTROS:?} || continue
|
||||||
|
echo "DISTROS:" "${DISTROS[@]}"
|
||||||
|
echo "EXTRAS->"
|
||||||
|
printf " %s\n" "${EXTRAS[@]}"
|
||||||
|
let n=1
|
||||||
|
for distro in "${DISTROS[@]}"; do
|
||||||
|
for extra in "${EXTRAS[@]:-NULL}"; do
|
||||||
|
# Magic value to let this for run once:
|
||||||
|
[[ ${extra} == NULL ]] && unset extra
|
||||||
|
docker rm -f "${NODES[@]}"
|
||||||
|
printf -v file_out "%s/%s-%02d.out" ${OUTPUT_DIR} ${spec} $((n++))
|
||||||
|
{
|
||||||
|
info "${distro}[${extra}] START: file_out=${file_out}"
|
||||||
|
time test_distro ${distro} ${extra}
|
||||||
|
} |& tee ${file_out}
|
||||||
|
# sleeping for the sake of the human to verify if they want
|
||||||
|
sleep 2m
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done
|
||||||
|
egrep -H '^(....:|real)' $(ls -tr ${OUTPUT_DIR}/*.out)
|
11
contrib/dind/test-most_distros-some_CNIs.env
Normal file
11
contrib/dind/test-most_distros-some_CNIs.env
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Test spec file: used from ./run-test-distros.sh, will run
|
||||||
|
# each distro in $DISTROS overloading main kubespray ansible-playbook run
|
||||||
|
# Get all DISTROS from distro.yaml (shame no yaml parsing, but nuff anyway)
|
||||||
|
# DISTROS="${*:-$(egrep -o '^ \w+' group_vars/all/distro.yaml|paste -s)}"
|
||||||
|
DISTROS=(debian ubuntu centos fedora)
|
||||||
|
|
||||||
|
# Each line below will be added as --extra-vars to main playbook run
|
||||||
|
EXTRAS=(
|
||||||
|
'kube_network_plugin=calico'
|
||||||
|
'kube_network_plugin=weave'
|
||||||
|
)
|
6
contrib/dind/test-some_distros-kube_router_combo.env
Normal file
6
contrib/dind/test-some_distros-kube_router_combo.env
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
DISTROS=(debian centos)
|
||||||
|
NETCHECKER_HOST=${NODES[0]}
|
||||||
|
EXTRAS=(
|
||||||
|
'kube_network_plugin=kube-router {"kube_router_run_service_proxy":false}'
|
||||||
|
'kube_network_plugin=kube-router {"kube_router_run_service_proxy":true}'
|
||||||
|
)
|
8
contrib/dind/test-some_distros-most_CNIs.env
Normal file
8
contrib/dind/test-some_distros-most_CNIs.env
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
DISTROS=(debian centos)
|
||||||
|
EXTRAS=(
|
||||||
|
'kube_network_plugin=calico {}'
|
||||||
|
'kube_network_plugin=canal {}'
|
||||||
|
'kube_network_plugin=cilium {}'
|
||||||
|
'kube_network_plugin=flannel {}'
|
||||||
|
'kube_network_plugin=weave {}'
|
||||||
|
)
|
480
contrib/inventory_builder/inventory.py
Normal file
480
contrib/inventory_builder/inventory.py
Normal file
|
@ -0,0 +1,480 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# Usage: inventory.py ip1 [ip2 ...]
|
||||||
|
# Examples: inventory.py 10.10.1.3 10.10.1.4 10.10.1.5
|
||||||
|
#
|
||||||
|
# Advanced usage:
|
||||||
|
# Add another host after initial creation: inventory.py 10.10.1.5
|
||||||
|
# Add range of hosts: inventory.py 10.10.1.3-10.10.1.5
|
||||||
|
# Add hosts with different ip and access ip:
|
||||||
|
# inventory.py 10.0.0.1,192.168.10.1 10.0.0.2,192.168.10.2 10.0.0.3,192.168.1.3
|
||||||
|
# Add hosts with a specific hostname, ip, and optional access ip:
|
||||||
|
# inventory.py first,10.0.0.1,192.168.10.1 second,10.0.0.2 last,10.0.0.3
|
||||||
|
# Delete a host: inventory.py -10.10.1.3
|
||||||
|
# Delete a host by id: inventory.py -node1
|
||||||
|
#
|
||||||
|
# Load a YAML or JSON file with inventory data: inventory.py load hosts.yaml
|
||||||
|
# YAML file should be in the following format:
|
||||||
|
# group1:
|
||||||
|
# host1:
|
||||||
|
# ip: X.X.X.X
|
||||||
|
# var: val
|
||||||
|
# group2:
|
||||||
|
# host2:
|
||||||
|
# ip: X.X.X.X
|
||||||
|
|
||||||
|
from collections import OrderedDict
|
||||||
|
from ipaddress import ip_address
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ROLES = ['all', 'kube_control_plane', 'kube_node', 'etcd', 'k8s_cluster',
|
||||||
|
'calico_rr']
|
||||||
|
PROTECTED_NAMES = ROLES
|
||||||
|
AVAILABLE_COMMANDS = ['help', 'print_cfg', 'print_ips', 'print_hostnames',
|
||||||
|
'load', 'add']
|
||||||
|
_boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
|
||||||
|
'0': False, 'no': False, 'false': False, 'off': False}
|
||||||
|
yaml = YAML()
|
||||||
|
yaml.Representer.add_representer(OrderedDict, yaml.Representer.represent_dict)
|
||||||
|
|
||||||
|
|
||||||
|
def get_var_as_bool(name, default):
|
||||||
|
value = os.environ.get(name, '')
|
||||||
|
return _boolean_states.get(value.lower(), default)
|
||||||
|
|
||||||
|
# Configurable as shell vars start
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_FILE = os.environ.get("CONFIG_FILE", "./inventory/sample/hosts.yaml")
|
||||||
|
# Remove the reference of KUBE_MASTERS after some deprecation cycles.
|
||||||
|
KUBE_CONTROL_HOSTS = int(os.environ.get("KUBE_CONTROL_HOSTS",
|
||||||
|
os.environ.get("KUBE_MASTERS", 2)))
|
||||||
|
# Reconfigures cluster distribution at scale
|
||||||
|
SCALE_THRESHOLD = int(os.environ.get("SCALE_THRESHOLD", 50))
|
||||||
|
MASSIVE_SCALE_THRESHOLD = int(os.environ.get("MASSIVE_SCALE_THRESHOLD", 200))
|
||||||
|
|
||||||
|
DEBUG = get_var_as_bool("DEBUG", True)
|
||||||
|
HOST_PREFIX = os.environ.get("HOST_PREFIX", "node")
|
||||||
|
USE_REAL_HOSTNAME = get_var_as_bool("USE_REAL_HOSTNAME", False)
|
||||||
|
|
||||||
|
# Configurable as shell vars end
|
||||||
|
|
||||||
|
|
||||||
|
class KubesprayInventory(object):
|
||||||
|
|
||||||
|
def __init__(self, changed_hosts=None, config_file=None):
|
||||||
|
self.config_file = config_file
|
||||||
|
self.yaml_config = {}
|
||||||
|
loadPreviousConfig = False
|
||||||
|
printHostnames = False
|
||||||
|
# See whether there are any commands to process
|
||||||
|
if changed_hosts and changed_hosts[0] in AVAILABLE_COMMANDS:
|
||||||
|
if changed_hosts[0] == "add":
|
||||||
|
loadPreviousConfig = True
|
||||||
|
changed_hosts = changed_hosts[1:]
|
||||||
|
elif changed_hosts[0] == "print_hostnames":
|
||||||
|
loadPreviousConfig = True
|
||||||
|
printHostnames = True
|
||||||
|
else:
|
||||||
|
self.parse_command(changed_hosts[0], changed_hosts[1:])
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
# If the user wants to remove a node, we need to load the config anyway
|
||||||
|
if changed_hosts and changed_hosts[0][0] == "-":
|
||||||
|
loadPreviousConfig = True
|
||||||
|
|
||||||
|
if self.config_file and loadPreviousConfig: # Load previous YAML file
|
||||||
|
try:
|
||||||
|
self.hosts_file = open(config_file, 'r')
|
||||||
|
self.yaml_config = yaml.load(self.hosts_file)
|
||||||
|
except OSError as e:
|
||||||
|
# I am assuming we are catching "cannot open file" exceptions
|
||||||
|
print(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if printHostnames:
|
||||||
|
self.print_hostnames()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
self.ensure_required_groups(ROLES)
|
||||||
|
|
||||||
|
if changed_hosts:
|
||||||
|
changed_hosts = self.range2ips(changed_hosts)
|
||||||
|
self.hosts = self.build_hostnames(changed_hosts,
|
||||||
|
loadPreviousConfig)
|
||||||
|
self.purge_invalid_hosts(self.hosts.keys(), PROTECTED_NAMES)
|
||||||
|
self.set_all(self.hosts)
|
||||||
|
self.set_k8s_cluster()
|
||||||
|
etcd_hosts_count = 3 if len(self.hosts.keys()) >= 3 else 1
|
||||||
|
self.set_etcd(list(self.hosts.keys())[:etcd_hosts_count])
|
||||||
|
if len(self.hosts) >= SCALE_THRESHOLD:
|
||||||
|
self.set_kube_control_plane(list(self.hosts.keys())[
|
||||||
|
etcd_hosts_count:(etcd_hosts_count + KUBE_CONTROL_HOSTS)])
|
||||||
|
else:
|
||||||
|
self.set_kube_control_plane(
|
||||||
|
list(self.hosts.keys())[:KUBE_CONTROL_HOSTS])
|
||||||
|
self.set_kube_node(self.hosts.keys())
|
||||||
|
if len(self.hosts) >= SCALE_THRESHOLD:
|
||||||
|
self.set_calico_rr(list(self.hosts.keys())[:etcd_hosts_count])
|
||||||
|
else: # Show help if no options
|
||||||
|
self.show_help()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
self.write_config(self.config_file)
|
||||||
|
|
||||||
|
def write_config(self, config_file):
|
||||||
|
if config_file:
|
||||||
|
with open(self.config_file, 'w') as f:
|
||||||
|
yaml.dump(self.yaml_config, f)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("WARNING: Unable to save config. Make sure you set "
|
||||||
|
"CONFIG_FILE env var.")
|
||||||
|
|
||||||
|
def debug(self, msg):
|
||||||
|
if DEBUG:
|
||||||
|
print("DEBUG: {0}".format(msg))
|
||||||
|
|
||||||
|
def get_ip_from_opts(self, optstring):
|
||||||
|
if 'ip' in optstring:
|
||||||
|
return optstring['ip']
|
||||||
|
else:
|
||||||
|
raise ValueError("IP parameter not found in options")
|
||||||
|
|
||||||
|
def ensure_required_groups(self, groups):
|
||||||
|
for group in groups:
|
||||||
|
if group == 'all':
|
||||||
|
self.debug("Adding group {0}".format(group))
|
||||||
|
if group not in self.yaml_config:
|
||||||
|
all_dict = OrderedDict([('hosts', OrderedDict({})),
|
||||||
|
('children', OrderedDict({}))])
|
||||||
|
self.yaml_config = {'all': all_dict}
|
||||||
|
else:
|
||||||
|
self.debug("Adding group {0}".format(group))
|
||||||
|
if group not in self.yaml_config['all']['children']:
|
||||||
|
self.yaml_config['all']['children'][group] = {'hosts': {}}
|
||||||
|
|
||||||
|
def get_host_id(self, host):
|
||||||
|
'''Returns integer host ID (without padding) from a given hostname.'''
|
||||||
|
try:
|
||||||
|
short_hostname = host.split('.')[0]
|
||||||
|
return int(re.findall("\\d+$", short_hostname)[-1])
|
||||||
|
except IndexError:
|
||||||
|
raise ValueError("Host name must end in an integer")
|
||||||
|
|
||||||
|
# Keeps already specified hosts,
|
||||||
|
# and adds or removes the hosts provided as an argument
|
||||||
|
def build_hostnames(self, changed_hosts, loadPreviousConfig=False):
|
||||||
|
existing_hosts = OrderedDict()
|
||||||
|
highest_host_id = 0
|
||||||
|
# Load already existing hosts from the YAML
|
||||||
|
if loadPreviousConfig:
|
||||||
|
try:
|
||||||
|
for host in self.yaml_config['all']['hosts']:
|
||||||
|
# Read configuration of an existing host
|
||||||
|
hostConfig = self.yaml_config['all']['hosts'][host]
|
||||||
|
existing_hosts[host] = hostConfig
|
||||||
|
# If the existing host seems
|
||||||
|
# to have been created automatically, detect its ID
|
||||||
|
if host.startswith(HOST_PREFIX):
|
||||||
|
host_id = self.get_host_id(host)
|
||||||
|
if host_id > highest_host_id:
|
||||||
|
highest_host_id = host_id
|
||||||
|
except Exception as e:
|
||||||
|
# I am assuming we are catching automatically
|
||||||
|
# created hosts without IDs
|
||||||
|
print(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# FIXME(mattymo): Fix condition where delete then add reuses highest id
|
||||||
|
next_host_id = highest_host_id + 1
|
||||||
|
next_host = ""
|
||||||
|
|
||||||
|
all_hosts = existing_hosts.copy()
|
||||||
|
for host in changed_hosts:
|
||||||
|
# Delete the host from config the hostname/IP has a "-" prefix
|
||||||
|
if host[0] == "-":
|
||||||
|
realhost = host[1:]
|
||||||
|
if self.exists_hostname(all_hosts, realhost):
|
||||||
|
self.debug("Marked {0} for deletion.".format(realhost))
|
||||||
|
all_hosts.pop(realhost)
|
||||||
|
elif self.exists_ip(all_hosts, realhost):
|
||||||
|
self.debug("Marked {0} for deletion.".format(realhost))
|
||||||
|
self.delete_host_by_ip(all_hosts, realhost)
|
||||||
|
# Host/Argument starts with a digit,
|
||||||
|
# then we assume its an IP address
|
||||||
|
elif host[0].isdigit():
|
||||||
|
if ',' in host:
|
||||||
|
ip, access_ip = host.split(',')
|
||||||
|
else:
|
||||||
|
ip = host
|
||||||
|
access_ip = host
|
||||||
|
if self.exists_hostname(all_hosts, host):
|
||||||
|
self.debug("Skipping existing host {0}.".format(host))
|
||||||
|
continue
|
||||||
|
elif self.exists_ip(all_hosts, ip):
|
||||||
|
self.debug("Skipping existing host {0}.".format(ip))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if USE_REAL_HOSTNAME:
|
||||||
|
cmd = ("ssh -oStrictHostKeyChecking=no "
|
||||||
|
+ access_ip + " 'hostname -s'")
|
||||||
|
next_host = subprocess.check_output(cmd, shell=True)
|
||||||
|
next_host = next_host.strip().decode('ascii')
|
||||||
|
else:
|
||||||
|
# Generates a hostname because we have only an IP address
|
||||||
|
next_host = "{0}{1}".format(HOST_PREFIX, next_host_id)
|
||||||
|
next_host_id += 1
|
||||||
|
# Uses automatically generated node name
|
||||||
|
# in case we dont provide it.
|
||||||
|
all_hosts[next_host] = {'ansible_host': access_ip,
|
||||||
|
'ip': ip,
|
||||||
|
'access_ip': access_ip}
|
||||||
|
# Host/Argument starts with a letter, then we assume its a hostname
|
||||||
|
elif host[0].isalpha():
|
||||||
|
if ',' in host:
|
||||||
|
try:
|
||||||
|
hostname, ip, access_ip = host.split(',')
|
||||||
|
except Exception:
|
||||||
|
hostname, ip = host.split(',')
|
||||||
|
access_ip = ip
|
||||||
|
if self.exists_hostname(all_hosts, host):
|
||||||
|
self.debug("Skipping existing host {0}.".format(host))
|
||||||
|
continue
|
||||||
|
elif self.exists_ip(all_hosts, ip):
|
||||||
|
self.debug("Skipping existing host {0}.".format(ip))
|
||||||
|
continue
|
||||||
|
all_hosts[hostname] = {'ansible_host': access_ip,
|
||||||
|
'ip': ip,
|
||||||
|
'access_ip': access_ip}
|
||||||
|
return all_hosts
|
||||||
|
|
||||||
|
# Expand IP ranges into individual addresses
|
||||||
|
def range2ips(self, hosts):
|
||||||
|
reworked_hosts = []
|
||||||
|
|
||||||
|
def ips(start_address, end_address):
|
||||||
|
try:
|
||||||
|
# Python 3.x
|
||||||
|
start = int(ip_address(start_address))
|
||||||
|
end = int(ip_address(end_address))
|
||||||
|
except Exception:
|
||||||
|
# Python 2.7
|
||||||
|
start = int(ip_address(str(start_address)))
|
||||||
|
end = int(ip_address(str(end_address)))
|
||||||
|
return [ip_address(ip).exploded for ip in range(start, end + 1)]
|
||||||
|
|
||||||
|
for host in hosts:
|
||||||
|
if '-' in host and not (host.startswith('-') or host[0].isalpha()):
|
||||||
|
start, end = host.strip().split('-')
|
||||||
|
try:
|
||||||
|
reworked_hosts.extend(ips(start, end))
|
||||||
|
except ValueError:
|
||||||
|
raise Exception("Range of ip_addresses isn't valid")
|
||||||
|
else:
|
||||||
|
reworked_hosts.append(host)
|
||||||
|
return reworked_hosts
|
||||||
|
|
||||||
|
def exists_hostname(self, existing_hosts, hostname):
|
||||||
|
return hostname in existing_hosts.keys()
|
||||||
|
|
||||||
|
def exists_ip(self, existing_hosts, ip):
|
||||||
|
for host_opts in existing_hosts.values():
|
||||||
|
if ip == self.get_ip_from_opts(host_opts):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def delete_host_by_ip(self, existing_hosts, ip):
|
||||||
|
for hostname, host_opts in existing_hosts.items():
|
||||||
|
if ip == self.get_ip_from_opts(host_opts):
|
||||||
|
del existing_hosts[hostname]
|
||||||
|
return
|
||||||
|
raise ValueError("Unable to find host by IP: {0}".format(ip))
|
||||||
|
|
||||||
|
def purge_invalid_hosts(self, hostnames, protected_names=[]):
|
||||||
|
for role in self.yaml_config['all']['children']:
|
||||||
|
if role != 'k8s_cluster' and self.yaml_config['all']['children'][role]['hosts']: # noqa
|
||||||
|
all_hosts = self.yaml_config['all']['children'][role]['hosts'].copy() # noqa
|
||||||
|
for host in all_hosts.keys():
|
||||||
|
if host not in hostnames and host not in protected_names:
|
||||||
|
self.debug(
|
||||||
|
"Host {0} removed from role {1}".format(host, role)) # noqa
|
||||||
|
del self.yaml_config['all']['children'][role]['hosts'][host] # noqa
|
||||||
|
# purge from all
|
||||||
|
if self.yaml_config['all']['hosts']:
|
||||||
|
all_hosts = self.yaml_config['all']['hosts'].copy()
|
||||||
|
for host in all_hosts.keys():
|
||||||
|
if host not in hostnames and host not in protected_names:
|
||||||
|
self.debug("Host {0} removed from role all".format(host))
|
||||||
|
del self.yaml_config['all']['hosts'][host]
|
||||||
|
|
||||||
|
def add_host_to_group(self, group, host, opts=""):
|
||||||
|
self.debug("adding host {0} to group {1}".format(host, group))
|
||||||
|
if group == 'all':
|
||||||
|
if self.yaml_config['all']['hosts'] is None:
|
||||||
|
self.yaml_config['all']['hosts'] = {host: None}
|
||||||
|
self.yaml_config['all']['hosts'][host] = opts
|
||||||
|
elif group != 'k8s_cluster:children':
|
||||||
|
if self.yaml_config['all']['children'][group]['hosts'] is None:
|
||||||
|
self.yaml_config['all']['children'][group]['hosts'] = {
|
||||||
|
host: None}
|
||||||
|
else:
|
||||||
|
self.yaml_config['all']['children'][group]['hosts'][host] = None # noqa
|
||||||
|
|
||||||
|
def set_kube_control_plane(self, hosts):
|
||||||
|
for host in hosts:
|
||||||
|
self.add_host_to_group('kube_control_plane', host)
|
||||||
|
|
||||||
|
def set_all(self, hosts):
|
||||||
|
for host, opts in hosts.items():
|
||||||
|
self.add_host_to_group('all', host, opts)
|
||||||
|
|
||||||
|
def set_k8s_cluster(self):
|
||||||
|
k8s_cluster = {'children': {'kube_control_plane': None,
|
||||||
|
'kube_node': None}}
|
||||||
|
self.yaml_config['all']['children']['k8s_cluster'] = k8s_cluster
|
||||||
|
|
||||||
|
def set_calico_rr(self, hosts):
|
||||||
|
for host in hosts:
|
||||||
|
if host in self.yaml_config['all']['children']['kube_control_plane']: # noqa
|
||||||
|
self.debug("Not adding {0} to calico_rr group because it "
|
||||||
|
"conflicts with kube_control_plane "
|
||||||
|
"group".format(host))
|
||||||
|
continue
|
||||||
|
if host in self.yaml_config['all']['children']['kube_node']:
|
||||||
|
self.debug("Not adding {0} to calico_rr group because it "
|
||||||
|
"conflicts with kube_node group".format(host))
|
||||||
|
continue
|
||||||
|
self.add_host_to_group('calico_rr', host)
|
||||||
|
|
||||||
|
def set_kube_node(self, hosts):
|
||||||
|
for host in hosts:
|
||||||
|
if len(self.yaml_config['all']['hosts']) >= SCALE_THRESHOLD:
|
||||||
|
if host in self.yaml_config['all']['children']['etcd']['hosts']: # noqa
|
||||||
|
self.debug("Not adding {0} to kube_node group because of "
|
||||||
|
"scale deployment and host is in etcd "
|
||||||
|
"group.".format(host))
|
||||||
|
continue
|
||||||
|
if len(self.yaml_config['all']['hosts']) >= MASSIVE_SCALE_THRESHOLD: # noqa
|
||||||
|
if host in self.yaml_config['all']['children']['kube_control_plane']['hosts']: # noqa
|
||||||
|
self.debug("Not adding {0} to kube_node group because of "
|
||||||
|
"scale deployment and host is in "
|
||||||
|
"kube_control_plane group.".format(host))
|
||||||
|
continue
|
||||||
|
self.add_host_to_group('kube_node', host)
|
||||||
|
|
||||||
|
def set_etcd(self, hosts):
|
||||||
|
for host in hosts:
|
||||||
|
self.add_host_to_group('etcd', host)
|
||||||
|
|
||||||
|
def load_file(self, files=None):
|
||||||
|
'''Directly loads JSON to inventory.'''
|
||||||
|
|
||||||
|
if not files:
|
||||||
|
raise Exception("No input file specified.")
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
for filename in list(files):
|
||||||
|
# Try JSON
|
||||||
|
try:
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
except ValueError:
|
||||||
|
raise Exception("Cannot read %s as JSON, or CSV", filename)
|
||||||
|
|
||||||
|
self.ensure_required_groups(ROLES)
|
||||||
|
self.set_k8s_cluster()
|
||||||
|
for group, hosts in data.items():
|
||||||
|
self.ensure_required_groups([group])
|
||||||
|
for host, opts in hosts.items():
|
||||||
|
optstring = {'ansible_host': opts['ip'],
|
||||||
|
'ip': opts['ip'],
|
||||||
|
'access_ip': opts['ip']}
|
||||||
|
self.add_host_to_group('all', host, optstring)
|
||||||
|
self.add_host_to_group(group, host)
|
||||||
|
self.write_config(self.config_file)
|
||||||
|
|
||||||
|
def parse_command(self, command, args=None):
|
||||||
|
if command == 'help':
|
||||||
|
self.show_help()
|
||||||
|
elif command == 'print_cfg':
|
||||||
|
self.print_config()
|
||||||
|
elif command == 'print_ips':
|
||||||
|
self.print_ips()
|
||||||
|
elif command == 'print_hostnames':
|
||||||
|
self.print_hostnames()
|
||||||
|
elif command == 'load':
|
||||||
|
self.load_file(args)
|
||||||
|
else:
|
||||||
|
raise Exception("Invalid command specified.")
|
||||||
|
|
||||||
|
def show_help(self):
|
||||||
|
help_text = '''Usage: inventory.py ip1 [ip2 ...]
|
||||||
|
Examples: inventory.py 10.10.1.3 10.10.1.4 10.10.1.5
|
||||||
|
|
||||||
|
Available commands:
|
||||||
|
help - Display this message
|
||||||
|
print_cfg - Write inventory file to stdout
|
||||||
|
print_ips - Write a space-delimited list of IPs from "all" group
|
||||||
|
print_hostnames - Write a space-delimited list of Hostnames from "all" group
|
||||||
|
add - Adds specified hosts into an already existing inventory
|
||||||
|
|
||||||
|
Advanced usage:
|
||||||
|
Create new or overwrite old inventory file: inventory.py 10.10.1.5
|
||||||
|
Add another host after initial creation: inventory.py add 10.10.1.6
|
||||||
|
Add range of hosts: inventory.py 10.10.1.3-10.10.1.5
|
||||||
|
Add hosts with different ip and access ip: inventory.py 10.0.0.1,192.168.10.1 10.0.0.2,192.168.10.2 10.0.0.3,192.168.10.3
|
||||||
|
Add hosts with a specific hostname, ip, and optional access ip: first,10.0.0.1,192.168.10.1 second,10.0.0.2 last,10.0.0.3
|
||||||
|
Delete a host: inventory.py -10.10.1.3
|
||||||
|
Delete a host by id: inventory.py -node1
|
||||||
|
|
||||||
|
Configurable env vars:
|
||||||
|
DEBUG Enable debug printing. Default: True
|
||||||
|
CONFIG_FILE File to write config to Default: ./inventory/sample/hosts.yaml
|
||||||
|
HOST_PREFIX Host prefix for generated hosts. Default: node
|
||||||
|
KUBE_CONTROL_HOSTS Set the number of kube-control-planes. Default: 2
|
||||||
|
SCALE_THRESHOLD Separate ETCD role if # of nodes >= 50
|
||||||
|
MASSIVE_SCALE_THRESHOLD Separate K8s control-plane and ETCD if # of nodes >= 200
|
||||||
|
''' # noqa
|
||||||
|
print(help_text)
|
||||||
|
|
||||||
|
def print_config(self):
|
||||||
|
yaml.dump(self.yaml_config, sys.stdout)
|
||||||
|
|
||||||
|
def print_hostnames(self):
|
||||||
|
print(' '.join(self.yaml_config['all']['hosts'].keys()))
|
||||||
|
|
||||||
|
def print_ips(self):
|
||||||
|
ips = []
|
||||||
|
for host, opts in self.yaml_config['all']['hosts'].items():
|
||||||
|
ips.append(self.get_ip_from_opts(opts))
|
||||||
|
print(' '.join(ips))
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv=None):
|
||||||
|
if not argv:
|
||||||
|
argv = sys.argv[1:]
|
||||||
|
KubesprayInventory(argv, CONFIG_FILE)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
3
contrib/inventory_builder/requirements.txt
Normal file
3
contrib/inventory_builder/requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
configparser>=3.3.0
|
||||||
|
ruamel.yaml>=0.15.88
|
||||||
|
ipaddress
|
3
contrib/inventory_builder/setup.cfg
Normal file
3
contrib/inventory_builder/setup.cfg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[metadata]
|
||||||
|
name = kubespray-inventory-builder
|
||||||
|
version = 0.1
|
29
contrib/inventory_builder/setup.py
Normal file
29
contrib/inventory_builder/setup.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
# implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
||||||
|
import setuptools
|
||||||
|
|
||||||
|
# In python < 2.7.4, a lazy loading of package `pbr` will break
|
||||||
|
# setuptools if some other modules registered functions in `atexit`.
|
||||||
|
# solution from: http://bugs.python.org/issue15881#msg170215
|
||||||
|
try:
|
||||||
|
import multiprocessing # noqa
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
setup_requires=[],
|
||||||
|
pbr=False)
|
3
contrib/inventory_builder/test-requirements.txt
Normal file
3
contrib/inventory_builder/test-requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
hacking>=0.10.2
|
||||||
|
pytest>=2.8.0
|
||||||
|
mock>=1.3.0
|
595
contrib/inventory_builder/tests/test_inventory.py
Normal file
595
contrib/inventory_builder/tests/test_inventory.py
Normal file
|
@ -0,0 +1,595 @@
|
||||||
|
# Copyright 2016 Mirantis, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import inventory
|
||||||
|
from io import StringIO
|
||||||
|
import unittest
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from collections import OrderedDict
|
||||||
|
import sys
|
||||||
|
|
||||||
|
path = "./contrib/inventory_builder/"
|
||||||
|
if path not in sys.path:
|
||||||
|
sys.path.append(path)
|
||||||
|
|
||||||
|
import inventory # noqa
|
||||||
|
|
||||||
|
|
||||||
|
class TestInventoryPrintHostnames(unittest.TestCase):
|
||||||
|
|
||||||
|
@mock.patch('ruamel.yaml.YAML.load')
|
||||||
|
def test_print_hostnames(self, load_mock):
|
||||||
|
mock_io = mock.mock_open(read_data='')
|
||||||
|
load_mock.return_value = OrderedDict({'all': {'hosts': {
|
||||||
|
'node1': {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'},
|
||||||
|
'node2': {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'}}}})
|
||||||
|
with mock.patch('builtins.open', mock_io):
|
||||||
|
with self.assertRaises(SystemExit) as cm:
|
||||||
|
with mock.patch('sys.stdout', new_callable=StringIO) as stdout:
|
||||||
|
inventory.KubesprayInventory(
|
||||||
|
changed_hosts=["print_hostnames"],
|
||||||
|
config_file="file")
|
||||||
|
self.assertEqual("node1 node2\n", stdout.getvalue())
|
||||||
|
self.assertEqual(cm.exception.code, 0)
|
||||||
|
|
||||||
|
|
||||||
|
class TestInventory(unittest.TestCase):
|
||||||
|
@mock.patch('inventory.sys')
|
||||||
|
def setUp(self, sys_mock):
|
||||||
|
sys_mock.exit = mock.Mock()
|
||||||
|
super(TestInventory, self).setUp()
|
||||||
|
self.data = ['10.90.3.2', '10.90.3.3', '10.90.3.4']
|
||||||
|
self.inv = inventory.KubesprayInventory()
|
||||||
|
|
||||||
|
def test_get_ip_from_opts(self):
|
||||||
|
optstring = {'ansible_host': '10.90.3.2',
|
||||||
|
'ip': '10.90.3.2',
|
||||||
|
'access_ip': '10.90.3.2'}
|
||||||
|
expected = "10.90.3.2"
|
||||||
|
result = self.inv.get_ip_from_opts(optstring)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_get_ip_from_opts_invalid(self):
|
||||||
|
optstring = "notanaddr=value something random!chars:D"
|
||||||
|
self.assertRaisesRegex(ValueError, "IP parameter not found",
|
||||||
|
self.inv.get_ip_from_opts, optstring)
|
||||||
|
|
||||||
|
def test_ensure_required_groups(self):
|
||||||
|
groups = ['group1', 'group2']
|
||||||
|
self.inv.ensure_required_groups(groups)
|
||||||
|
for group in groups:
|
||||||
|
self.assertIn(group, self.inv.yaml_config['all']['children'])
|
||||||
|
|
||||||
|
def test_get_host_id(self):
|
||||||
|
hostnames = ['node99', 'no99de01', '01node01', 'node1.domain',
|
||||||
|
'node3.xyz123.aaa']
|
||||||
|
expected = [99, 1, 1, 1, 3]
|
||||||
|
for hostname, expected in zip(hostnames, expected):
|
||||||
|
result = self.inv.get_host_id(hostname)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_get_host_id_invalid(self):
|
||||||
|
bad_hostnames = ['node', 'no99de', '01node', 'node.111111']
|
||||||
|
for hostname in bad_hostnames:
|
||||||
|
self.assertRaisesRegex(ValueError, "Host name must end in an",
|
||||||
|
self.inv.get_host_id, hostname)
|
||||||
|
|
||||||
|
def test_build_hostnames_add_duplicate(self):
|
||||||
|
changed_hosts = ['10.90.0.2']
|
||||||
|
expected = OrderedDict([('node3',
|
||||||
|
{'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = expected
|
||||||
|
result = self.inv.build_hostnames(changed_hosts, True)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_add_two(self):
|
||||||
|
changed_hosts = ['10.90.0.2', '10.90.0.3']
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = OrderedDict()
|
||||||
|
result = self.inv.build_hostnames(changed_hosts)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_add_three(self):
|
||||||
|
changed_hosts = ['10.90.0.2', '10.90.0.3', '10.90.0.4']
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'}),
|
||||||
|
('node3', {'ansible_host': '10.90.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '10.90.0.4'})])
|
||||||
|
result = self.inv.build_hostnames(changed_hosts)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_add_one(self):
|
||||||
|
changed_hosts = ['10.90.0.2']
|
||||||
|
expected = OrderedDict([('node1',
|
||||||
|
{'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'})])
|
||||||
|
result = self.inv.build_hostnames(changed_hosts)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_delete_first(self):
|
||||||
|
changed_hosts = ['-10.90.0.2']
|
||||||
|
existing_hosts = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing_hosts
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
result = self.inv.build_hostnames(changed_hosts, True)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_delete_by_hostname(self):
|
||||||
|
changed_hosts = ['-node1']
|
||||||
|
existing_hosts = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing_hosts
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
result = self.inv.build_hostnames(changed_hosts, True)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_exists_hostname_positive(self):
|
||||||
|
hostname = 'node1'
|
||||||
|
expected = True
|
||||||
|
existing_hosts = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
result = self.inv.exists_hostname(existing_hosts, hostname)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_exists_hostname_negative(self):
|
||||||
|
hostname = 'node99'
|
||||||
|
expected = False
|
||||||
|
existing_hosts = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
result = self.inv.exists_hostname(existing_hosts, hostname)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_exists_ip_positive(self):
|
||||||
|
ip = '10.90.0.2'
|
||||||
|
expected = True
|
||||||
|
existing_hosts = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
result = self.inv.exists_ip(existing_hosts, ip)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_exists_ip_negative(self):
|
||||||
|
ip = '10.90.0.200'
|
||||||
|
expected = False
|
||||||
|
existing_hosts = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
result = self.inv.exists_ip(existing_hosts, ip)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_delete_host_by_ip_positive(self):
|
||||||
|
ip = '10.90.0.2'
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
existing_hosts = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
self.inv.delete_host_by_ip(existing_hosts, ip)
|
||||||
|
self.assertEqual(expected, existing_hosts)
|
||||||
|
|
||||||
|
def test_delete_host_by_ip_negative(self):
|
||||||
|
ip = '10.90.0.200'
|
||||||
|
existing_hosts = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'})])
|
||||||
|
self.assertRaisesRegex(ValueError, "Unable to find host",
|
||||||
|
self.inv.delete_host_by_ip, existing_hosts, ip)
|
||||||
|
|
||||||
|
def test_purge_invalid_hosts(self):
|
||||||
|
proper_hostnames = ['node1', 'node2']
|
||||||
|
bad_host = 'doesnotbelong2'
|
||||||
|
existing_hosts = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '10.90.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '10.90.0.2'}),
|
||||||
|
('node2', {'ansible_host': '10.90.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '10.90.0.3'}),
|
||||||
|
('doesnotbelong2', {'whateveropts=ilike'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing_hosts
|
||||||
|
self.inv.purge_invalid_hosts(proper_hostnames)
|
||||||
|
self.assertNotIn(
|
||||||
|
bad_host, self.inv.yaml_config['all']['hosts'].keys())
|
||||||
|
|
||||||
|
def test_add_host_to_group(self):
|
||||||
|
group = 'etcd'
|
||||||
|
host = 'node1'
|
||||||
|
opts = {'ip': '10.90.0.2'}
|
||||||
|
|
||||||
|
self.inv.add_host_to_group(group, host, opts)
|
||||||
|
self.assertEqual(
|
||||||
|
self.inv.yaml_config['all']['children'][group]['hosts'].get(host),
|
||||||
|
None)
|
||||||
|
|
||||||
|
def test_set_kube_control_plane(self):
|
||||||
|
group = 'kube_control_plane'
|
||||||
|
host = 'node1'
|
||||||
|
|
||||||
|
self.inv.set_kube_control_plane([host])
|
||||||
|
self.assertIn(
|
||||||
|
host, self.inv.yaml_config['all']['children'][group]['hosts'])
|
||||||
|
|
||||||
|
def test_set_all(self):
|
||||||
|
hosts = OrderedDict([
|
||||||
|
('node1', 'opt1'),
|
||||||
|
('node2', 'opt2')])
|
||||||
|
|
||||||
|
self.inv.set_all(hosts)
|
||||||
|
for host, opt in hosts.items():
|
||||||
|
self.assertEqual(
|
||||||
|
self.inv.yaml_config['all']['hosts'].get(host), opt)
|
||||||
|
|
||||||
|
def test_set_k8s_cluster(self):
|
||||||
|
group = 'k8s_cluster'
|
||||||
|
expected_hosts = ['kube_node', 'kube_control_plane']
|
||||||
|
|
||||||
|
self.inv.set_k8s_cluster()
|
||||||
|
for host in expected_hosts:
|
||||||
|
self.assertIn(
|
||||||
|
host,
|
||||||
|
self.inv.yaml_config['all']['children'][group]['children'])
|
||||||
|
|
||||||
|
def test_set_kube_node(self):
|
||||||
|
group = 'kube_node'
|
||||||
|
host = 'node1'
|
||||||
|
|
||||||
|
self.inv.set_kube_node([host])
|
||||||
|
self.assertIn(
|
||||||
|
host, self.inv.yaml_config['all']['children'][group]['hosts'])
|
||||||
|
|
||||||
|
def test_set_etcd(self):
|
||||||
|
group = 'etcd'
|
||||||
|
host = 'node1'
|
||||||
|
|
||||||
|
self.inv.set_etcd([host])
|
||||||
|
self.assertIn(
|
||||||
|
host, self.inv.yaml_config['all']['children'][group]['hosts'])
|
||||||
|
|
||||||
|
def test_scale_scenario_one(self):
|
||||||
|
num_nodes = 50
|
||||||
|
hosts = OrderedDict()
|
||||||
|
|
||||||
|
for hostid in range(1, num_nodes+1):
|
||||||
|
hosts["node" + str(hostid)] = ""
|
||||||
|
|
||||||
|
self.inv.set_all(hosts)
|
||||||
|
self.inv.set_etcd(list(hosts.keys())[0:3])
|
||||||
|
self.inv.set_kube_control_plane(list(hosts.keys())[0:2])
|
||||||
|
self.inv.set_kube_node(hosts.keys())
|
||||||
|
for h in range(3):
|
||||||
|
self.assertFalse(
|
||||||
|
list(hosts.keys())[h] in
|
||||||
|
self.inv.yaml_config['all']['children']['kube_node']['hosts'])
|
||||||
|
|
||||||
|
def test_scale_scenario_two(self):
|
||||||
|
num_nodes = 500
|
||||||
|
hosts = OrderedDict()
|
||||||
|
|
||||||
|
for hostid in range(1, num_nodes+1):
|
||||||
|
hosts["node" + str(hostid)] = ""
|
||||||
|
|
||||||
|
self.inv.set_all(hosts)
|
||||||
|
self.inv.set_etcd(list(hosts.keys())[0:3])
|
||||||
|
self.inv.set_kube_control_plane(list(hosts.keys())[3:5])
|
||||||
|
self.inv.set_kube_node(hosts.keys())
|
||||||
|
for h in range(5):
|
||||||
|
self.assertFalse(
|
||||||
|
list(hosts.keys())[h] in
|
||||||
|
self.inv.yaml_config['all']['children']['kube_node']['hosts'])
|
||||||
|
|
||||||
|
def test_range2ips_range(self):
|
||||||
|
changed_hosts = ['10.90.0.2', '10.90.0.4-10.90.0.6', '10.90.0.8']
|
||||||
|
expected = ['10.90.0.2',
|
||||||
|
'10.90.0.4',
|
||||||
|
'10.90.0.5',
|
||||||
|
'10.90.0.6',
|
||||||
|
'10.90.0.8']
|
||||||
|
result = self.inv.range2ips(changed_hosts)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_range2ips_incorrect_range(self):
|
||||||
|
host_range = ['10.90.0.4-a.9b.c.e']
|
||||||
|
self.assertRaisesRegex(Exception, "Range of ip_addresses isn't valid",
|
||||||
|
self.inv.range2ips, host_range)
|
||||||
|
|
||||||
|
def test_build_hostnames_create_with_one_different_ips(self):
|
||||||
|
changed_hosts = ['10.90.0.2,192.168.0.2']
|
||||||
|
expected = OrderedDict([('node1',
|
||||||
|
{'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'})])
|
||||||
|
result = self.inv.build_hostnames(changed_hosts)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_create_with_two_different_ips(self):
|
||||||
|
changed_hosts = ['10.90.0.2,192.168.0.2', '10.90.0.3,192.168.0.3']
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node2', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'})])
|
||||||
|
result = self.inv.build_hostnames(changed_hosts)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_create_with_three_different_ips(self):
|
||||||
|
changed_hosts = ['10.90.0.2,192.168.0.2',
|
||||||
|
'10.90.0.3,192.168.0.3',
|
||||||
|
'10.90.0.4,192.168.0.4']
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node1', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node2', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'}),
|
||||||
|
('node3', {'ansible_host': '192.168.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '192.168.0.4'})])
|
||||||
|
result = self.inv.build_hostnames(changed_hosts)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_overwrite_one_with_different_ips(self):
|
||||||
|
changed_hosts = ['10.90.0.2,192.168.0.2']
|
||||||
|
expected = OrderedDict([('node1',
|
||||||
|
{'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'})])
|
||||||
|
existing = OrderedDict([('node5',
|
||||||
|
{'ansible_host': '192.168.0.5',
|
||||||
|
'ip': '10.90.0.5',
|
||||||
|
'access_ip': '192.168.0.5'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing
|
||||||
|
result = self.inv.build_hostnames(changed_hosts)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_overwrite_three_with_different_ips(self):
|
||||||
|
changed_hosts = ['10.90.0.2,192.168.0.2']
|
||||||
|
expected = OrderedDict([('node1',
|
||||||
|
{'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'})])
|
||||||
|
existing = OrderedDict([
|
||||||
|
('node3', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'}),
|
||||||
|
('node4', {'ansible_host': '192.168.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '192.168.0.4'}),
|
||||||
|
('node5', {'ansible_host': '192.168.0.5',
|
||||||
|
'ip': '10.90.0.5',
|
||||||
|
'access_ip': '192.168.0.5'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing
|
||||||
|
result = self.inv.build_hostnames(changed_hosts)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_different_ips_add_duplicate(self):
|
||||||
|
changed_hosts = ['10.90.0.2,192.168.0.2']
|
||||||
|
expected = OrderedDict([('node3',
|
||||||
|
{'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'})])
|
||||||
|
existing = expected
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing
|
||||||
|
result = self.inv.build_hostnames(changed_hosts, True)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_add_two_different_ips_into_one_existing(self):
|
||||||
|
changed_hosts = ['10.90.0.3,192.168.0.3', '10.90.0.4,192.168.0.4']
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node3', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'}),
|
||||||
|
('node4', {'ansible_host': '192.168.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '192.168.0.4'})])
|
||||||
|
|
||||||
|
existing = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing
|
||||||
|
result = self.inv.build_hostnames(changed_hosts, True)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_add_two_different_ips_into_two_existing(self):
|
||||||
|
changed_hosts = ['10.90.0.4,192.168.0.4', '10.90.0.5,192.168.0.5']
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node3', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'}),
|
||||||
|
('node4', {'ansible_host': '192.168.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '192.168.0.4'}),
|
||||||
|
('node5', {'ansible_host': '192.168.0.5',
|
||||||
|
'ip': '10.90.0.5',
|
||||||
|
'access_ip': '192.168.0.5'})])
|
||||||
|
|
||||||
|
existing = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node3', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing
|
||||||
|
result = self.inv.build_hostnames(changed_hosts, True)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
def test_build_hostnames_add_two_different_ips_into_three_existing(self):
|
||||||
|
changed_hosts = ['10.90.0.5,192.168.0.5', '10.90.0.6,192.168.0.6']
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node3', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'}),
|
||||||
|
('node4', {'ansible_host': '192.168.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '192.168.0.4'}),
|
||||||
|
('node5', {'ansible_host': '192.168.0.5',
|
||||||
|
'ip': '10.90.0.5',
|
||||||
|
'access_ip': '192.168.0.5'}),
|
||||||
|
('node6', {'ansible_host': '192.168.0.6',
|
||||||
|
'ip': '10.90.0.6',
|
||||||
|
'access_ip': '192.168.0.6'})])
|
||||||
|
|
||||||
|
existing = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node3', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'}),
|
||||||
|
('node4', {'ansible_host': '192.168.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '192.168.0.4'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing
|
||||||
|
result = self.inv.build_hostnames(changed_hosts, True)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
# Add two IP addresses into a config that has
|
||||||
|
# three already defined IP addresses. One of the IP addresses
|
||||||
|
# is a duplicate.
|
||||||
|
def test_build_hostnames_add_two_duplicate_one_overlap(self):
|
||||||
|
changed_hosts = ['10.90.0.4,192.168.0.4', '10.90.0.5,192.168.0.5']
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node3', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'}),
|
||||||
|
('node4', {'ansible_host': '192.168.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '192.168.0.4'}),
|
||||||
|
('node5', {'ansible_host': '192.168.0.5',
|
||||||
|
'ip': '10.90.0.5',
|
||||||
|
'access_ip': '192.168.0.5'})])
|
||||||
|
|
||||||
|
existing = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node3', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'}),
|
||||||
|
('node4', {'ansible_host': '192.168.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '192.168.0.4'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing
|
||||||
|
result = self.inv.build_hostnames(changed_hosts, True)
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
# Add two duplicate IP addresses into a config that has
|
||||||
|
# three already defined IP addresses
|
||||||
|
def test_build_hostnames_add_two_duplicate_two_overlap(self):
|
||||||
|
changed_hosts = ['10.90.0.3,192.168.0.3', '10.90.0.4,192.168.0.4']
|
||||||
|
expected = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node3', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'}),
|
||||||
|
('node4', {'ansible_host': '192.168.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '192.168.0.4'})])
|
||||||
|
|
||||||
|
existing = OrderedDict([
|
||||||
|
('node2', {'ansible_host': '192.168.0.2',
|
||||||
|
'ip': '10.90.0.2',
|
||||||
|
'access_ip': '192.168.0.2'}),
|
||||||
|
('node3', {'ansible_host': '192.168.0.3',
|
||||||
|
'ip': '10.90.0.3',
|
||||||
|
'access_ip': '192.168.0.3'}),
|
||||||
|
('node4', {'ansible_host': '192.168.0.4',
|
||||||
|
'ip': '10.90.0.4',
|
||||||
|
'access_ip': '192.168.0.4'})])
|
||||||
|
self.inv.yaml_config['all']['hosts'] = existing
|
||||||
|
result = self.inv.build_hostnames(changed_hosts, True)
|
||||||
|
self.assertEqual(expected, result)
|
28
contrib/inventory_builder/tox.ini
Normal file
28
contrib/inventory_builder/tox.ini
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[tox]
|
||||||
|
minversion = 1.6
|
||||||
|
skipsdist = True
|
||||||
|
envlist = pep8, py33
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
whitelist_externals = py.test
|
||||||
|
usedevelop = True
|
||||||
|
deps =
|
||||||
|
-r{toxinidir}/requirements.txt
|
||||||
|
-r{toxinidir}/test-requirements.txt
|
||||||
|
setenv = VIRTUAL_ENV={envdir}
|
||||||
|
passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
|
||||||
|
commands = pytest -vv #{posargs:./tests}
|
||||||
|
|
||||||
|
[testenv:pep8]
|
||||||
|
usedevelop = False
|
||||||
|
whitelist_externals = bash
|
||||||
|
commands =
|
||||||
|
bash -c "find {toxinidir}/* -type f -name '*.py' -print0 | xargs -0 flake8"
|
||||||
|
|
||||||
|
[testenv:venv]
|
||||||
|
commands = {posargs}
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
show-source = true
|
||||||
|
builtins = _
|
||||||
|
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg
|
11
contrib/kvm-setup/README.md
Normal file
11
contrib/kvm-setup/README.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Kubespray on KVM Virtual Machines hypervisor preparation
|
||||||
|
|
||||||
|
A simple playbook to ensure your system has the right settings to enable Kubespray
|
||||||
|
deployment on VMs.
|
||||||
|
|
||||||
|
This playbook does not create Virtual Machines, nor does it run Kubespray itself.
|
||||||
|
|
||||||
|
## User creation
|
||||||
|
|
||||||
|
If you want to create a user for running Kubespray deployment, you should specify
|
||||||
|
both `k8s_deployment_user` and `k8s_deployment_user_pkey_path`.
|
3
contrib/kvm-setup/group_vars/all
Normal file
3
contrib/kvm-setup/group_vars/all
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#k8s_deployment_user: kubespray
|
||||||
|
#k8s_deployment_user_pkey_path: /tmp/ssh_rsa
|
||||||
|
|
8
contrib/kvm-setup/kvm-setup.yml
Normal file
8
contrib/kvm-setup/kvm-setup.yml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
gather_facts: False
|
||||||
|
become: yes
|
||||||
|
vars:
|
||||||
|
- bootstrap_os: none
|
||||||
|
roles:
|
||||||
|
- kvm-setup
|
30
contrib/kvm-setup/roles/kvm-setup/tasks/main.yml
Normal file
30
contrib/kvm-setup/roles/kvm-setup/tasks/main.yml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Install required packages
|
||||||
|
package:
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: present
|
||||||
|
with_items:
|
||||||
|
- bind-utils
|
||||||
|
- ntp
|
||||||
|
when: ansible_os_family == "RedHat"
|
||||||
|
|
||||||
|
- name: Install required packages
|
||||||
|
apt:
|
||||||
|
upgrade: yes
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 3600
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: present
|
||||||
|
install_recommends: no
|
||||||
|
with_items:
|
||||||
|
- dnsutils
|
||||||
|
- ntp
|
||||||
|
when: ansible_os_family == "Debian"
|
||||||
|
|
||||||
|
# Create deployment user if required
|
||||||
|
- include: user.yml
|
||||||
|
when: k8s_deployment_user is defined
|
||||||
|
|
||||||
|
# Set proper sysctl values
|
||||||
|
- include: sysctl.yml
|
46
contrib/kvm-setup/roles/kvm-setup/tasks/sysctl.yml
Normal file
46
contrib/kvm-setup/roles/kvm-setup/tasks/sysctl.yml
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
- name: Load br_netfilter module
|
||||||
|
modprobe:
|
||||||
|
name: br_netfilter
|
||||||
|
state: present
|
||||||
|
register: br_netfilter
|
||||||
|
|
||||||
|
- name: Add br_netfilter into /etc/modules
|
||||||
|
lineinfile:
|
||||||
|
dest: /etc/modules
|
||||||
|
state: present
|
||||||
|
line: 'br_netfilter'
|
||||||
|
when: br_netfilter is defined and ansible_os_family == 'Debian'
|
||||||
|
|
||||||
|
- name: Add br_netfilter into /etc/modules-load.d/kubespray.conf
|
||||||
|
copy:
|
||||||
|
dest: /etc/modules-load.d/kubespray.conf
|
||||||
|
content: |-
|
||||||
|
### This file is managed by Ansible
|
||||||
|
br-netfilter
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0644
|
||||||
|
when: br_netfilter is defined
|
||||||
|
|
||||||
|
|
||||||
|
- name: Enable net.ipv4.ip_forward in sysctl
|
||||||
|
sysctl:
|
||||||
|
name: net.ipv4.ip_forward
|
||||||
|
value: 1
|
||||||
|
sysctl_file: "{{ sysctl_file_path }}"
|
||||||
|
state: present
|
||||||
|
reload: yes
|
||||||
|
|
||||||
|
- name: Set bridge-nf-call-{arptables,iptables} to 0
|
||||||
|
sysctl:
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: present
|
||||||
|
value: 0
|
||||||
|
sysctl_file: "{{ sysctl_file_path }}"
|
||||||
|
reload: yes
|
||||||
|
with_items:
|
||||||
|
- net.bridge.bridge-nf-call-arptables
|
||||||
|
- net.bridge.bridge-nf-call-ip6tables
|
||||||
|
- net.bridge.bridge-nf-call-iptables
|
||||||
|
when: br_netfilter is defined
|
47
contrib/kvm-setup/roles/kvm-setup/tasks/user.yml
Normal file
47
contrib/kvm-setup/roles/kvm-setup/tasks/user.yml
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
---
|
||||||
|
- name: Create user {{ k8s_deployment_user }}
|
||||||
|
user:
|
||||||
|
name: "{{ k8s_deployment_user }}"
|
||||||
|
groups: adm
|
||||||
|
shell: /bin/bash
|
||||||
|
|
||||||
|
- name: Ensure that .ssh exists
|
||||||
|
file:
|
||||||
|
path: "/home/{{ k8s_deployment_user }}/.ssh"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ k8s_deployment_user }}"
|
||||||
|
group: "{{ k8s_deployment_user }}"
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: Configure sudo for deployment user
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
%{{ k8s_deployment_user }} ALL=(ALL) NOPASSWD: ALL
|
||||||
|
dest: "/etc/sudoers.d/55-k8s-deployment"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: 0644
|
||||||
|
|
||||||
|
- name: Write private SSH key
|
||||||
|
copy:
|
||||||
|
src: "{{ k8s_deployment_user_pkey_path }}"
|
||||||
|
dest: "/home/{{ k8s_deployment_user }}/.ssh/id_rsa"
|
||||||
|
mode: 0400
|
||||||
|
owner: "{{ k8s_deployment_user }}"
|
||||||
|
group: "{{ k8s_deployment_user }}"
|
||||||
|
when: k8s_deployment_user_pkey_path is defined
|
||||||
|
|
||||||
|
- name: Write public SSH key
|
||||||
|
shell: "ssh-keygen -y -f /home/{{ k8s_deployment_user }}/.ssh/id_rsa \
|
||||||
|
> /home/{{ k8s_deployment_user }}/.ssh/authorized_keys"
|
||||||
|
args:
|
||||||
|
creates: "/home/{{ k8s_deployment_user }}/.ssh/authorized_keys"
|
||||||
|
when: k8s_deployment_user_pkey_path is defined
|
||||||
|
|
||||||
|
- name: Fix ssh-pub-key permissions
|
||||||
|
file:
|
||||||
|
path: "/home/{{ k8s_deployment_user }}/.ssh/authorized_keys"
|
||||||
|
mode: 0600
|
||||||
|
owner: "{{ k8s_deployment_user }}"
|
||||||
|
group: "{{ k8s_deployment_user }}"
|
||||||
|
when: k8s_deployment_user_pkey_path is defined
|
15
contrib/misc/clusteradmin-rbac.yml
Normal file
15
contrib/misc/clusteradmin-rbac.yml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
labels:
|
||||||
|
k8s-app: kubernetes-dashboard
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: cluster-admin
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kubernetes-dashboard
|
||||||
|
namespace: kube-system
|
49
contrib/mitogen/mitogen.yml
Normal file
49
contrib/mitogen/mitogen.yml
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
---
|
||||||
|
- name: Check ansible version
|
||||||
|
import_playbook: ansible_version.yml
|
||||||
|
|
||||||
|
- hosts: localhost
|
||||||
|
strategy: linear
|
||||||
|
vars:
|
||||||
|
mitogen_version: 0.3.2
|
||||||
|
mitogen_url: https://github.com/mitogen-hq/mitogen/archive/refs/tags/v{{ mitogen_version }}.tar.gz
|
||||||
|
ansible_connection: local
|
||||||
|
tasks:
|
||||||
|
- name: Create mitogen plugin dir
|
||||||
|
file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
mode: 0755
|
||||||
|
become: false
|
||||||
|
loop:
|
||||||
|
- "{{ playbook_dir }}/plugins/mitogen"
|
||||||
|
- "{{ playbook_dir }}/dist"
|
||||||
|
|
||||||
|
- name: download mitogen release
|
||||||
|
get_url:
|
||||||
|
url: "{{ mitogen_url }}"
|
||||||
|
dest: "{{ playbook_dir }}/dist/mitogen_{{ mitogen_version }}.tar.gz"
|
||||||
|
validate_certs: true
|
||||||
|
|
||||||
|
- name: extract archive
|
||||||
|
unarchive:
|
||||||
|
src: "{{ playbook_dir }}/dist/mitogen_{{ mitogen_version }}.tar.gz"
|
||||||
|
dest: "{{ playbook_dir }}/dist/"
|
||||||
|
|
||||||
|
- name: copy plugin
|
||||||
|
synchronize:
|
||||||
|
src: "{{ playbook_dir }}/dist/mitogen-{{ mitogen_version }}/"
|
||||||
|
dest: "{{ playbook_dir }}/plugins/mitogen"
|
||||||
|
|
||||||
|
- name: add strategy to ansible.cfg
|
||||||
|
ini_file:
|
||||||
|
path: ansible.cfg
|
||||||
|
mode: 0644
|
||||||
|
section: "{{ item.section | d('defaults') }}"
|
||||||
|
option: "{{ item.option }}"
|
||||||
|
value: "{{ item.value }}"
|
||||||
|
with_items:
|
||||||
|
- option: strategy
|
||||||
|
value: mitogen_linear
|
||||||
|
- option: strategy_plugins
|
||||||
|
value: plugins/mitogen/ansible_mitogen/plugins/strategy
|
92
contrib/network-storage/glusterfs/README.md
Normal file
92
contrib/network-storage/glusterfs/README.md
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
# Deploying a Kubespray Kubernetes Cluster with GlusterFS
|
||||||
|
|
||||||
|
You can either deploy using Ansible on its own by supplying your own inventory file or by using Terraform to create the VMs and then providing a dynamic inventory to Ansible. The following two sections are self-contained, you don't need to go through one to use the other. So, if you want to provision with Terraform, you can skip the **Using an Ansible inventory** section, and if you want to provision with a pre-built ansible inventory, you can neglect the **Using Terraform and Ansible** section.
|
||||||
|
|
||||||
|
## Using an Ansible inventory
|
||||||
|
|
||||||
|
In the same directory of this ReadMe file you should find a file named `inventory.example` which contains an example setup. Please note that, additionally to the Kubernetes nodes/masters, we define a set of machines for GlusterFS and we add them to the group `[gfs-cluster]`, which in turn is added to the larger `[network-storage]` group as a child group.
|
||||||
|
|
||||||
|
Change that file to reflect your local setup (adding more machines or removing them and setting the adequate ip numbers), and save it to `inventory/sample/k8s_gfs_inventory`. Make sure that the settings on `inventory/sample/group_vars/all.yml` make sense with your deployment. Then execute change to the kubespray root folder, and execute (supposing that the machines are all using ubuntu):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ansible-playbook -b --become-user=root -i inventory/sample/k8s_gfs_inventory --user=ubuntu ./cluster.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
This will provision your Kubernetes cluster. Then, to provision and configure the GlusterFS cluster, from the same directory execute:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ansible-playbook -b --become-user=root -i inventory/sample/k8s_gfs_inventory --user=ubuntu ./contrib/network-storage/glusterfs/glusterfs.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
If your machines are not using Ubuntu, you need to change the `--user=ubuntu` to the correct user. Alternatively, if your Kubernetes machines are using one OS and your GlusterFS a different one, you can instead specify the `ansible_ssh_user=<correct-user>` variable in the inventory file that you just created, for each machine/VM:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
k8s-master-1 ansible_ssh_host=192.168.0.147 ip=192.168.0.147 ansible_ssh_user=core
|
||||||
|
k8s-master-node-1 ansible_ssh_host=192.168.0.148 ip=192.168.0.148 ansible_ssh_user=core
|
||||||
|
k8s-master-node-2 ansible_ssh_host=192.168.0.146 ip=192.168.0.146 ansible_ssh_user=core
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using Terraform and Ansible
|
||||||
|
|
||||||
|
First step is to fill in a `my-kubespray-gluster-cluster.tfvars` file with the specification desired for your cluster. An example with all required variables would look like:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
cluster_name = "cluster1"
|
||||||
|
number_of_k8s_masters = "1"
|
||||||
|
number_of_k8s_masters_no_floating_ip = "2"
|
||||||
|
number_of_k8s_nodes_no_floating_ip = "0"
|
||||||
|
number_of_k8s_nodes = "0"
|
||||||
|
public_key_path = "~/.ssh/my-desired-key.pub"
|
||||||
|
image = "Ubuntu 16.04"
|
||||||
|
ssh_user = "ubuntu"
|
||||||
|
flavor_k8s_node = "node-flavor-id-in-your-openstack"
|
||||||
|
flavor_k8s_master = "master-flavor-id-in-your-openstack"
|
||||||
|
network_name = "k8s-network"
|
||||||
|
floatingip_pool = "net_external"
|
||||||
|
|
||||||
|
# GlusterFS variables
|
||||||
|
flavor_gfs_node = "gluster-flavor-id-in-your-openstack"
|
||||||
|
image_gfs = "Ubuntu 16.04"
|
||||||
|
number_of_gfs_nodes_no_floating_ip = "3"
|
||||||
|
gfs_volume_size_in_gb = "50"
|
||||||
|
ssh_user_gfs = "ubuntu"
|
||||||
|
```
|
||||||
|
|
||||||
|
As explained in the general terraform/openstack guide, you need to source your OpenStack credentials file, add your ssh-key to the ssh-agent and setup environment variables for terraform:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ source ~/.stackrc
|
||||||
|
$ eval $(ssh-agent -s)
|
||||||
|
$ ssh-add ~/.ssh/my-desired-key
|
||||||
|
$ echo Setting up Terraform creds && \
|
||||||
|
export TF_VAR_username=${OS_USERNAME} && \
|
||||||
|
export TF_VAR_password=${OS_PASSWORD} && \
|
||||||
|
export TF_VAR_tenant=${OS_TENANT_NAME} && \
|
||||||
|
export TF_VAR_auth_url=${OS_AUTH_URL}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, standing on the kubespray directory (root base of the Git checkout), issue the following terraform command to create the VMs for the cluster:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform apply -state=contrib/terraform/openstack/terraform.tfstate -var-file=my-kubespray-gluster-cluster.tfvars contrib/terraform/openstack
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create both your Kubernetes and Gluster VMs. Make sure that the ansible file `contrib/terraform/openstack/group_vars/all.yml` includes any ansible variable that you want to setup (like, for instance, the type of machine for bootstrapping).
|
||||||
|
|
||||||
|
Then, provision your Kubernetes (kubespray) cluster with the following ansible call:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ansible-playbook -b --become-user=root -i contrib/terraform/openstack/hosts ./cluster.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, provision the glusterfs nodes and add the Persistent Volume setup for GlusterFS in Kubernetes through the following ansible call:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ansible-playbook -b --become-user=root -i contrib/terraform/openstack/hosts ./contrib/network-storage/glusterfs/glusterfs.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to destroy the cluster, you can run:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform destroy -state=contrib/terraform/openstack/terraform.tfstate -var-file=my-kubespray-gluster-cluster.tfvars contrib/terraform/openstack
|
||||||
|
```
|
24
contrib/network-storage/glusterfs/glusterfs.yml
Normal file
24
contrib/network-storage/glusterfs/glusterfs.yml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
- hosts: gfs-cluster
|
||||||
|
gather_facts: false
|
||||||
|
vars:
|
||||||
|
ansible_ssh_pipelining: false
|
||||||
|
roles:
|
||||||
|
- { role: bootstrap-os, tags: bootstrap-os}
|
||||||
|
|
||||||
|
- hosts: all
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
- hosts: gfs-cluster
|
||||||
|
vars:
|
||||||
|
ansible_ssh_pipelining: true
|
||||||
|
roles:
|
||||||
|
- { role: glusterfs/server }
|
||||||
|
|
||||||
|
- hosts: k8s_cluster
|
||||||
|
roles:
|
||||||
|
- { role: glusterfs/client }
|
||||||
|
|
||||||
|
- hosts: kube_control_plane[0]
|
||||||
|
roles:
|
||||||
|
- { role: kubernetes-pv }
|
1
contrib/network-storage/glusterfs/group_vars
Symbolic link
1
contrib/network-storage/glusterfs/group_vars
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../inventory/local/group_vars
|
44
contrib/network-storage/glusterfs/inventory.example
Normal file
44
contrib/network-storage/glusterfs/inventory.example
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# ## Configure 'ip' variable to bind kubernetes services on a
|
||||||
|
# ## different ip than the default iface
|
||||||
|
# node1 ansible_ssh_host=95.54.0.12 # ip=10.3.0.1
|
||||||
|
# node2 ansible_ssh_host=95.54.0.13 # ip=10.3.0.2
|
||||||
|
# node3 ansible_ssh_host=95.54.0.14 # ip=10.3.0.3
|
||||||
|
# node4 ansible_ssh_host=95.54.0.15 # ip=10.3.0.4
|
||||||
|
# node5 ansible_ssh_host=95.54.0.16 # ip=10.3.0.5
|
||||||
|
# node6 ansible_ssh_host=95.54.0.17 # ip=10.3.0.6
|
||||||
|
#
|
||||||
|
# ## GlusterFS nodes
|
||||||
|
# ## Set disk_volume_device_1 to desired device for gluster brick, if different to /dev/vdb (default).
|
||||||
|
# ## As in the previous case, you can set ip to give direct communication on internal IPs
|
||||||
|
# gfs_node1 ansible_ssh_host=95.54.0.18 # disk_volume_device_1=/dev/vdc ip=10.3.0.7
|
||||||
|
# gfs_node2 ansible_ssh_host=95.54.0.19 # disk_volume_device_1=/dev/vdc ip=10.3.0.8
|
||||||
|
# gfs_node3 ansible_ssh_host=95.54.0.20 # disk_volume_device_1=/dev/vdc ip=10.3.0.9
|
||||||
|
|
||||||
|
# [kube_control_plane]
|
||||||
|
# node1
|
||||||
|
# node2
|
||||||
|
|
||||||
|
# [etcd]
|
||||||
|
# node1
|
||||||
|
# node2
|
||||||
|
# node3
|
||||||
|
|
||||||
|
# [kube_node]
|
||||||
|
# node2
|
||||||
|
# node3
|
||||||
|
# node4
|
||||||
|
# node5
|
||||||
|
# node6
|
||||||
|
|
||||||
|
# [k8s_cluster:children]
|
||||||
|
# kube_node
|
||||||
|
# kube_control_plane
|
||||||
|
|
||||||
|
# [gfs-cluster]
|
||||||
|
# gfs_node1
|
||||||
|
# gfs_node2
|
||||||
|
# gfs_node3
|
||||||
|
|
||||||
|
# [network-storage:children]
|
||||||
|
# gfs-cluster
|
||||||
|
|
1
contrib/network-storage/glusterfs/roles/bootstrap-os
Symbolic link
1
contrib/network-storage/glusterfs/roles/bootstrap-os
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../../roles/bootstrap-os
|
50
contrib/network-storage/glusterfs/roles/glusterfs/README.md
Normal file
50
contrib/network-storage/glusterfs/roles/glusterfs/README.md
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# Ansible Role: GlusterFS
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/geerlingguy/ansible-role-glusterfs.svg?branch=master)](https://travis-ci.org/geerlingguy/ansible-role-glusterfs)
|
||||||
|
|
||||||
|
Installs and configures GlusterFS on Linux.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
For GlusterFS to connect between servers, TCP ports `24007`, `24008`, and `24009`/`49152`+ (that port, plus an additional incremented port for each additional server in the cluster; the latter if GlusterFS is version 3.4+), and TCP/UDP port `111` must be open. You can open these using whatever firewall you wish (this can easily be configured using the `geerlingguy.firewall` role).
|
||||||
|
|
||||||
|
This role performs basic installation and setup of Gluster, but it does not configure or mount bricks (volumes), since that step is easier to do in a series of plays in your own playbook. Ansible 1.9+ includes the [`gluster_volume`](https://docs.ansible.com/ansible/latest/collections/gluster/gluster/gluster_volume_module.html) module to ease the management of Gluster volumes.
|
||||||
|
|
||||||
|
## Role Variables
|
||||||
|
|
||||||
|
Available variables are listed below, along with default values (see `defaults/main.yml`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
glusterfs_default_release: ""
|
||||||
|
```
|
||||||
|
|
||||||
|
You can specify a `default_release` for apt on Debian/Ubuntu by overriding this variable. This is helpful if you need a different package or version for the main GlusterFS packages (e.g. GlusterFS 3.5.x instead of 3.2.x with the `wheezy-backports` default release on Debian Wheezy).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
glusterfs_ppa_use: yes
|
||||||
|
glusterfs_ppa_version: "3.5"
|
||||||
|
```
|
||||||
|
|
||||||
|
For Ubuntu, specify whether to use the official Gluster PPA, and which version of the PPA to use. See Gluster's [Getting Started Guide](https://docs.gluster.org/en/latest/Quick-Start-Guide/Quickstart/) for more info.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
## Example Playbook
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- hosts: server
|
||||||
|
roles:
|
||||||
|
- geerlingguy.glusterfs
|
||||||
|
```
|
||||||
|
|
||||||
|
For a real-world use example, read through [Simple GlusterFS Setup with Ansible](http://www.jeffgeerling.com/blog/simple-glusterfs-setup-ansible), a blog post by this role's author, which is included in Chapter 8 of [Ansible for DevOps](https://www.ansiblefordevops.com/).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT / BSD
|
||||||
|
|
||||||
|
## Author Information
|
||||||
|
|
||||||
|
This role was created in 2015 by [Jeff Geerling](http://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/).
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
# For Ubuntu.
|
||||||
|
glusterfs_default_release: ""
|
||||||
|
glusterfs_ppa_use: yes
|
||||||
|
glusterfs_ppa_version: "4.1"
|
||||||
|
|
||||||
|
# Gluster configuration.
|
||||||
|
gluster_mount_dir: /mnt/gluster
|
||||||
|
gluster_volume_node_mount_dir: /mnt/xfs-drive-gluster
|
||||||
|
gluster_brick_dir: "{{ gluster_volume_node_mount_dir }}/brick"
|
||||||
|
gluster_brick_name: gluster
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue