From b8547fd8bf1c6f8140fc89d9d60d0d4121af5862 Mon Sep 17 00:00:00 2001 From: Artem Goncharov Date: Fri, 11 Feb 2022 14:18:09 +0100 Subject: [PATCH] add first blueprint (#1) add first blueprint Reviewed-by: kucerakk Reviewed-by: Vladimir Hasko Reviewed-by: Artem Goncharov --- .gitignore | 26 + .pre-commit-config.yaml | 32 ++ .zuul.yaml | 5 + bindep.txt | 5 + doc/requirements.txt | 12 + doc/source/_static/css/.placeholder | 0 doc/source/_static/css/default.css | 7 + doc/source/_static/favicon.ico | Bin 0 -> 1406 bytes doc/source/_static/images/ansible.svg | 10 + doc/source/_static/images/docker.svg | 1 + doc/source/_static/images/golang.svg | 45 ++ doc/source/_static/images/javascript.svg | 54 ++ doc/source/_static/images/k8_pod.png | Bin 0 -> 13799 bytes doc/source/_static/images/k8_svc.png | Bin 0 -> 12015 bytes doc/source/_static/images/otc.png | Bin 0 -> 16338 bytes doc/source/_static/images/python.svg | 113 +++++ doc/source/_static/images/rancher.svg | 1 + doc/source/_static/images/terraform.svg | 1 + doc/source/_static/images/users.png | Bin 0 -> 5205 bytes doc/source/_static/images/vault.png | Bin 0 -> 7000 bytes doc/source/_static/images/zookeeper.png | Bin 0 -> 26639 bytes doc/source/cce_vault.rst | 618 +++++++++++++++++++++++ doc/source/conf.py | 80 +++ doc/source/dot/cce_vault_overview.dot | 23 + doc/source/index.rst | 15 + setup.cfg | 21 + setup.py | 18 + tox.ini | 26 + 28 files changed, 1113 insertions(+) create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 .zuul.yaml create mode 100644 bindep.txt create mode 100644 doc/requirements.txt create mode 100644 doc/source/_static/css/.placeholder create mode 100644 doc/source/_static/css/default.css create mode 100644 doc/source/_static/favicon.ico create mode 100644 doc/source/_static/images/ansible.svg create mode 100644 doc/source/_static/images/docker.svg create mode 100644 doc/source/_static/images/golang.svg create mode 100644 doc/source/_static/images/javascript.svg create mode 100644 doc/source/_static/images/k8_pod.png create mode 100644 doc/source/_static/images/k8_svc.png create mode 100644 doc/source/_static/images/otc.png create mode 100644 doc/source/_static/images/python.svg create mode 100644 doc/source/_static/images/rancher.svg create mode 100644 doc/source/_static/images/terraform.svg create mode 100644 doc/source/_static/images/users.png create mode 100644 doc/source/_static/images/vault.png create mode 100644 doc/source/_static/images/zookeeper.png create mode 100644 doc/source/cce_vault.rst create mode 100644 doc/source/conf.py create mode 100644 doc/source/dot/cce_vault_overview.dot create mode 100644 doc/source/index.rst create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c19e2b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +_build/ +/AUTHORS +/ChangeLog +/dist/ +/otcdocstheme.egg-info/ +.DS_Store +*.pyc +doc/build +doc/source/BBresult +api-ref/build +.tox +/.venv +*.swp +*.log +*.egg* + +# Editors +*~ + +# Files created by releasenotes build +releasenotes/build + +# Files created by the LaTeX/PDF build +/.aux +/.fdb_latexmk +/texput.fls diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..1a96af9 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,32 @@ +default_language_version: + python: python3 +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: 9136088a246768144165fcc3ecc3d31bb686920a # v3.3.0 + hooks: + - id: trailing-whitespace + # Replaces or checks mixed line ending + - id: mixed-line-ending + args: ['--fix', 'lf'] + exclude: '.*\.(svg)$' + # Forbid files which have a UTF-8 byte-order marker + - id: check-byte-order-marker + # Checks that non-binary executables have a proper shebang + - id: check-executables-have-shebangs + # Check for files that contain merge conflict strings. + - id: check-merge-conflict + # Check for debugger imports and py37+ breakpoint() + # calls in python source + - id: debug-statements + - id: check-yaml + files: .*\.(yaml|yml)$ + - repo: local + hooks: + - id: flake8 + name: flake8 + additional_dependencies: + - hacking>=3.0.1,<3.1.0 + language: python + entry: flake8 + files: '^.*\.py$' + exclude: '^(doc|releasenotes|tools)/.*$' diff --git a/.zuul.yaml b/.zuul.yaml new file mode 100644 index 0000000..bc0e80a --- /dev/null +++ b/.zuul.yaml @@ -0,0 +1,5 @@ +- project: + merge-mode: squash-merge + default-branch: main + templates: + - publish-otc-docs-hc-pti diff --git a/bindep.txt b/bindep.txt new file mode 100644 index 0000000..5bee0c6 --- /dev/null +++ b/bindep.txt @@ -0,0 +1,5 @@ +libffi-dev [platform:dpkg] +libffi-devel [platform:rpm] +libssl-dev [platform:dpkg] +openssl-devel [platform:rpm] +graphviz [doc] diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 0000000..0528130 --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1,12 @@ +# The order of packages is significant, because pip processes them in the order +# of appearance. Changing the order has an impact on the overall integration +# process, which may cause wedges in the gate later. +# Notes: +# reno needs openstackdocstheme which needs reno (cycle dep). +# os-api-ref needs openstackdocstheme which needs os-api-ref (cycle dep). +# Put them in here will make it clear that those are only needed for +# docs. + +sphinx==4.0.0 +otcdocstheme +reno>=3.1.0 # Apache-2.0 diff --git a/doc/source/_static/css/.placeholder b/doc/source/_static/css/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/doc/source/_static/css/default.css b/doc/source/_static/css/default.css new file mode 100644 index 0000000..e2c3119 --- /dev/null +++ b/doc/source/_static/css/default.css @@ -0,0 +1,7 @@ +.literal-block-wrapper { + padding: 0 !important; +} + +.highlight .nv { + color: var(--dt-color-text-standard) !important; +} diff --git a/doc/source/_static/favicon.ico b/doc/source/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..cf837fc7a5c39f29757061295936c477e95fc7b1 GIT binary patch literal 1406 zcmeH@Jx>Bb5Qg8o14U6eQSp;yw&Mr*i>xd)epHsmg33n!gQc3Nor#H-CNzREF^0ei z7(u{z;BlV2cSo+UurRT@cQccDX5QUw22jM&b%-3pY7|HT$chjxkO7Xo*iBb(yw*hV!i4!|quc&MtJ23NN^l&< z`(K#D4TKx`*A4KWiY$^VJ>t*U_&m{clm*rqqS=5rj}c7{Sls0qq70XX&~Gd~u3u3U zSx*d@^Q2@-_;a3t%Nq0iO!GLNW-5`&QVSl_*ys|`@X!ePOf*L{CH~>Ed?V0bm;DV8 Ca&4^u literal 0 HcmV?d00001 diff --git a/doc/source/_static/images/ansible.svg b/doc/source/_static/images/ansible.svg new file mode 100644 index 0000000..b8196d5 --- /dev/null +++ b/doc/source/_static/images/ansible.svg @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/doc/source/_static/images/docker.svg b/doc/source/_static/images/docker.svg new file mode 100644 index 0000000..a2473ad --- /dev/null +++ b/doc/source/_static/images/docker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/doc/source/_static/images/golang.svg b/doc/source/_static/images/golang.svg new file mode 100644 index 0000000..cab722f --- /dev/null +++ b/doc/source/_static/images/golang.svg @@ -0,0 +1,45 @@ + + Gopher + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/source/_static/images/javascript.svg b/doc/source/_static/images/javascript.svg new file mode 100644 index 0000000..b1428d6 --- /dev/null +++ b/doc/source/_static/images/javascript.svg @@ -0,0 +1,54 @@ + + + Slice 1 + + + + image/svg+xml + + Slice 1 + + + + + + + + + + + + + diff --git a/doc/source/_static/images/k8_pod.png b/doc/source/_static/images/k8_pod.png new file mode 100644 index 0000000000000000000000000000000000000000..e498a9af6581e1be80f8cb668be3448bef2e4fe4 GIT binary patch literal 13799 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 F|9@2x+KvDK literal 0 HcmV?d00001 diff --git a/doc/source/_static/images/k8_svc.png b/doc/source/_static/images/k8_svc.png new file mode 100644 index 0000000000000000000000000000000000000000..8cca4806f071ec151ecb43e6c512f9e124099621 GIT binary patch literal 12015 zcmX9^bzD6v02ly8q?DF-=5Cf3O6%9Zo9wd}^G{~IASqP}^1kxKoKquR!G!JP{9n6* z-{$1z@}}qh=sJIH{(ef$;*Vf1EBSlIQCG9grjy3XmcjnP{(slJ7&{$eUh9K{S#|sC z+^Oz+E&GH0K5HM=n^oF|6C4PZ{^PY{&k zyJsk~8Cq%FYWN==L|2^J%L>&^#v2zagR8;P1+NODzr}<>De={IB#+ zp(SCBn|Oq1DBvDxlNGm}`mhrU$H7IE0!|n_B$84Glb-^=>#WaEtm&RTE<5tXJr!n* zjE-Qb2=aGpWM>LHxoHf7Ec!6M{Cq6TieCwI@w^ESVnR&=zL-I@Ta!r*6Jmc~XfIf3 z|8B19;;G9n+xU{fmr2W~%=Fs0@d0`ad17Snafp(DKoT~(Lvd>hWQDZdd)+4}GC2@f zVW;-Gg_|#vH+Iir_UUDE%#S##0^;Gb7X5pRRE#ev2fb4d&``JxF2VtD3cIC{kT~Cl z65h^lwf`dg4eNwr@>HT5m&0tSRjzO0{^}Zewqr_wl{TduIIst@N#c1}g$wxgfLzJya0wF0;p$`Y zH%DP%u^At4bL{k5G=;#;m=~|X%@pZy2jGAM$gYGV>Bv#IjG-<-0|j~+s0s!ts-6BT zz8K)Xt+vV^dz?T>zymuOtltT8vRiBa{cnvJ=ojXi$6dq%_mYBpLC!D^2+o@>q*O;~ zozJ-g4EcJ0F(<$XhJnV_v{MNQe)}PPtmLo5Y?!h@AkJa{;}JCpt@{IV0E1ZC62lun zhYXJ$1PGlBy?V_ObgsJF<86OlILgxPzxdC9?~IVMG6vIh#C6jOXoC>E`BVu|qTq}; z=xcxu3P0Ito@BchP*vKxQafZP|82g*Ne`u-;~w{KaZIpq|G`L~05wXb`?CSi3|qut zJfb8qx(vf&h`~j;L6jqIbtN{wHcm!hWOJ6x{*AaTq1`>g6^mus>lqTDO&4RyvqW;w zJ_LM`P83(tJSkxe{*^!|1c9VO$pcsSC5MeXD~K)^{?&O7Wtfb|{k`yrOPF9W;@Pf+(4UaAK)<-DdPCU9>d(J|`dymnH?gDbZrXyz#3}(mxkk z%O9_XF9@gID^BHomS^+lef}rp@Uk0cSeyKTaN$!TP$3xL(jE~(gtzxL^u|2D$sQUk zjMHYFz24Q!CVFcIVP#0W_u2f%%1Q1WH8@sV0(9}=l~}OEef1EjB^DSbK#dz@d_^_9 zaNyN^qwn}n{`vL~-1dD}1BI{Z^Ldk>%bMIgdQEc|TS$R8$T=TMH?rtQ&cPqL8@FPH z&<&zn?wf((C3~;N@23)hItJ~85?7h@Jj$$@J9#vRp175k)N^n$;0M` zkhW4F6pjHA#WuxL(fgLdc0 zqK=#c^N*hFz#GxiYPfV~HecIJbx~!!>W?ViQY*KG0R63E12$n_cBO-#+Q2v@m0(ep z@e%*S=G4zdcqq6z=M~{C{)WT(P>adxwNqXq5jxV9)5`63Ct>_=y-DUvQw@c8@NtZD z5mZX#My1r!_XoSuAZP1ni4qCLq1UUgTmPyKmeiC@?+N#%_E6?krY049A<@)X2(Y!I zh>mL9YB*_tH!C9}VEEit3N|2HF(E;;CPAG+O{1+=5hZQB@x1XJ4jSnNMjxs!_MX%J zBiB5LC073bDg9w#R9aXRw{0EDs!!1{JWzgK>5lhed(QXFB^TmT_{ zY!oqR@czZ&mlC>W;j)ll`P=@of~a?Zs60}H5TE-Gb0~m|VC~3ObE}E#^9Si}TMd?Z zILr+YwzYhM`zOk=Rb=o!6B}^)EH2FD2t7c6I%*!$5l!j(7 z`RJ(J8pw7hbbj3Xf$Z+$K*Dw7UKn3))NX!Z_Z;QJS;08qJ|~i%cT)2XCl-V^&g#^V0Ihk<%;&=S9K$~w(=Ty{i6YnC_C>$@j`f@t@V^;Fg&llP!J6O-SFhL-X zmHHH>+>Z;Ayd^~$gYtF!JyvsZSkK{0`{iKkFpy7KA#;An_+({Zb1;sIwWUd_4eNlJ zxJ-btTrIK@6e0-!m^?I+M6@Xr6^}j3{4TPJTjfideecWgDC^ne!9`V&9I=tliPT9@ zXzm-M1N!*+XXo2$^==vVt2gE>uKr z{HKSxP&m(_D8{XjL{X-nbdIlUy!$}rSxNZh)AJMN5X;meo)u;LpVjr2;~qcxiDVBP z9k@~3OkxsnUeJnCmlmwW9yeSR8ES19US3`G#@EJ5s|wqMN8t@Vs{9}t^juE6{$8>f zF4v@`7|K3sgCj&nM2Z<}@iE|4r!xfN{_TWtwDCoeop;Ogd^v`v;k+Mij5t}i=hF2j z%0hfdUs6EXP*KPlQRpXGIgrJ7z?^*Yeb76?Qg8d8$M4YA_NC*rx6LY41=~ z`l#lIH)UFnad?>T|HFY%0EjMApd`mN*%$<(rrX$~#@g>rgXm7?r}*t>{g2c7SYwrh zab^lt0tgn(8Sl&eAi;y2)1jYL9r+ecU5q{Z>_b-D>X2t)ma4Z@%=^>+V_E_)Fw@<; zpo~0@jp5EhY|+LK7M92KXWKZtu~|OQrU0) z?6#cBt8}Jh6|=dsXPssmqXCwH_|fjR|43XX+6+KQdbQ~M#=CjCVrTd;R6$_tpBz3q zEMfAyg|qew<+)*a6vt_bk8lOIYgq#6EF^|+YZ_cIZO5HFc|PGRF`REbN#DsV${naR zPk0jmu`8}nIFEF&;c2oZ~%xev(LIq@3I1ML;h<)PC01`*Gd3fVS2XAlII2Tqp+dM*x zADhO&r4fuK4cWHivl4Qt*F23>1eE67> zbx+^q&lcf7I~1Z5RY?HGMtEq3+A5X|>X2RtnrD|dMSf~4GZ(4xfF26m@*0tYF*!|^ zRN;+z>S@nJK)IWu`W!CGE=L^k==6iz$H4FrbJzI3N9r@29j0{w+wD*)K za&qBk74)5$?VsF+=oHl*2!Iuc@1&F0*0bFRvzf;n_21?aaz~^iE6ej`kwB)Cy5atP zcC$e8PG)8T!3ImKXE>}oO*4YN4cZQtgwXQYWmGD+-)8P2Pk~1y3`4H z1pr><9@0IJGwk7q?DzV3at1)iP=Mt4 z&K*`U3WA4aMT#0{f47lQ6Y>Q#Fottu37c<*cpOc~jJ?A0A6j8bS^&fpjw1cTNQ!l%4FsI$Nj;jH)g3G(F$y=sm%#RRo;|=1(f1#7pQ^QyOJB zUP9il--Z=LI4s{C>9A{RafUHac7iKSgj|E*iOo!Jd56Rm)yJ_UJAoA|40vbg8?xC< zm4sY%=|}n5x2rTB5WSx02|cD2?djRme< z-vji+o+khq|Ivj+XK4I@-+WR+ZV?`Ecbn3jGaFUU-}>SswCexh$V_47d?1vBk$5JP z^Y_A}Bxzt$2s}wNkbg1EKRXTbzf{otBW3xoSzEr)ikW1Q80zDldb?pWg!6{Bbc^yb z0aZ8xWshym!JDB(_de!&mv3WP6rNLwFWI8`L1>6L4@iF2FY)n94&$c*$l!_I2f}ytg=80=&FU(XX#dd9rgpsCdD$nSh2U+Kx4x={)qX}fq z{_^Hj!W`TFdad8XUS-@L`f}5$Q(wPMRZQT*6bjd2bgTD#Cx9o}@_fgIAMe-ac5fDm z?$EaDCpffEv?)aIQ#U2?xY}scbmEF64ym-Sm(U#S_-VuOJnm0-bo_`L6^sOfaZ zeK|HG7EB8*qCuVdF#6SLV|pKj$9PVklVmC8CAj`P=(=D3_;OAxRI)5zsK`vR7<1<&8OSUDHVzNaEapSuWz;9q zG=*?L)4RBe_NI7b$8-P>xE%9j#QOID2Li$SsKIL zLEvOowfL)pyMF~++s&~9sfXI_l&-_;rAhj})6_1Up%*{9DnH`!3(i0Ci}SvBI#}U^qGooM>_w7_Qivgm8vOnfXJNWCLvE!)^ZpGqIpS{>dU_DSyw|{u0W- z570h3WB%~p!+il^O%_?BQ1~d*r3b-(KIRlOxF$9rJ73QZSAz_Aj4}Myv0Uejk`G3r zZ%5s{SDRqr3{aPfcPfNENhL6Xw1AYABMVA_IKXB$u)3lZ42ugVxy*RUK*%@NpjSS z+__5L7mh951HYIpB_?LTpkpO_YlH_x^E=#gMVEKB(*(aD1HM3PmS5a?8PQ6IYR%+Z z?^Jm1_a$5@JjpUm(k9V6_3~b90$tgBBRL?G(FXqjIL!Cmk)?P`${Pf=@Y<0kf!ihUNpJ$mjpc{y8HPYY8vbELGuPxx7GFF
    #Lkh4 z;ApNY&4YDzF)WY^6ezwO1Zy5*H`#0J&?0>FnqW7gQ4hHP`#ILH!}C2IjYFrDO(~Er9o@kCVp^z$FR=V8SGs zemT{+W$@Lg@^$D9pe-gp(_F-imlV$RgV$GsbRsx` zb)u@}WCF`CyB(cf0(8VTj%F5yxFGfj89J$(S0~IIUF!k#P__u*8o>)Zo>}bWWkrUY z#aONr51A>BME!1c+af4joN4HrXDU?(^@=#z$*uQCv`i@crz8hdZJku)PJo9$y~5JN zbIj0+5H%GV!OGj@`;NeTq#mI8q{IyOMlEqc?iS-O;z@o;^ zp|5LfEN&U(QTA5@sW7k$BY@)hAcR^#Wef;t%A%SL)r!g8)p_t-$#(Xpkho>L`=0^J zS$wMSD2%s6jeJkv;&2@J0WUhInJtZQ!p;7KZeeF9AAhNUO0FHRn*@a`I=GPm#cMVh zY2H{Uvp<>rT8TQUzdr$LDyO#f>K}O#AY1Id9#vZQq)ntiu^a?iCHyMw)laND3gM?U zHm{D$H2{UuEh`!=_+m%=m; zYWk(L#{Q#^O+kpa1kl-qI5S>)DBYJYG4KpO2Q2$a0I>;5ihSh*Q#ME!SSMw~fO2`s z4`%zU)x&4R|412&F%DGq%c43H|H)?G;RPa~rwR{MKzTs_X1JY&W z#2V}3nM||lT|CM$>cb;7w_ENB+L~8b=Wil)00@L3R~n%2v0Jy!=)N&eu+aDJw4`L6 z)9YWk={{+uW*kj#5BhU1k?xEU_yBc+nUihwhw@oXq2qH(b4$t}3^x~jrAc2rg`em3 zE<|l~z59m;zEB1%R9Zd+&^IYKRijTd$i!J=%*@{#aJyac6g4?E%Ozz2bWS(Y(MSg5 z2|G&HQa6Ki>*}z-x#ca?IfL;PC2Q%)zTM-SRqZ$gwRR>@&Xzl~#$Egh>I+5RpEjx* z`(W1A`Z#eNgOXM5t~R(p|C1LoOnr769QlIpI*S!Ru0UKcP$5+!Di6}129BoYlYPSM z<550m2u_vYb58sf%Ew=Poff(Fg{)`|%ABhKOiER0!cj*%18LXzNBx%`vfygHG(LWJ z+rTyZY=(neMI5Qr$EJ36KgsG^ZVDW;d|IvC@+d%h*`vC zvqeZp*2~$UT78X`u94#5g=~e&vm&+`1RAWniF=C{8X{ohMW@Wf0rN90!M&Gkp&MAH zguwJ+Q@Nip_iSt3l-R@6OHf;dj|;51Y4l7*bn|+lfCPdut#BPvidH}s`5h>ba=KsD z;uG}ZMRJIWG|YmzUd4mc`SW24kV>t*j1x=>_P}z7fGZteCM;`z(dfH1q!{?6B6R0b zGJhYu17Z&{0&0$cItCjEE)N09!!SOr7u}#Z)g>|6p*V2+lY_`h!OM;G50fmQ z?67#q&=CEsV{A5+22aCYC9$(tlydioyZqi+J6ESFY?ls75RXWl{5EhV0+1f0fr;-O z9OJEwvwv6k$scpIoLNz>c?7<;pGdfJIJSv>R01dyt^RJr0)R+`<2Oi!pxdv8+!>*i z1&)S1%$wcM!)I$*uj8N%agow5g9sG?02TQgVAyq=DjnaRmv<+SX_4rx@j7zvk1%d! z%A;AaqUS~#L@Ed~JIB7qVnA~P3T(84JC@>??b!v2)%W;dd2yhn{!?AiVMppy|FR+; z5p?uX61k2agZs5ko1*c_xAJ<-rciLNmn5Pw;te|J=Jz+3SG9wr8C^P_uQW?36abJl z)P?zUPWo}M&ia`pDo}7J}<7fBWDpX&U00NyY zVREN{B+?HuhaD6w&CgkJBU)$?;lY;?n(FyoOjk(fWZQg#`fML?u@~wWe@XcW09R*Y zc&k$b2Z>QJ!8GQxK zd1bexz%~2_Y+PDpN1(3{x$vmliP2JqktiBBGTGZYHQI*CC6NJE$VYSx!FPAAg}aFG zd8V-@mY$bCWk6@v&vQ7~Wu~~z{b00s+PaF^ivBUUTIdd{;2uOB-TW2(Ak~>UC8I*RujwRm1GTw9wRsZs*gVWeCZ> z9lnsrT=TclZvjkY=}G9r#9wLtPQA~Tai#>3T#v%>B;4tH^)npCo?c#ottKY2p)Z)P z1#;AJ5nRDRK5Di0DUGM<(X#*zMPyV_rNupFTGt{nrX0oa0dHFqVqFY-iXjGQ(oG~7eZD{+Xn9Sw3sR+VmZY=wBDN0!Wo6bd$+u>?P+1oMg5(a+2+-UoxR z4z>kB(|=ah(N*gOR;HsxiT{|Ld^agQAB?YmZS+dO@G|}*bSS_O$N~WOQtxH~ZZB^Q zjn~H_RwBZ|+CC$JcX^D=s? zTV9~ChsWBERqmv!*1N2xHyZ4F6qO#gv!S$_g0CD%26t@2e=#~+ZYvoI87|2da^4ng z9mW4V?+mhAOx*n;6t*Ph$X1Sp;+}k}RKcHtTQQduK=74MI!%cqzMp$i!ra zYr3)Ri?wAQUvhP$zU$3mBB9MKFA>Ji6h>6Mupc=OfS#Wn`SxEo-us+X=(W$MNoL3+ zgg5!+#PELD!tbQor)={cALWwhf&LgZp|blV|M@p5TvsCCSEe;mA??y7&gW0*Xu5A9 z_v4NwsvqYNwxE9jQ163VZPR^qpQ9Dl3Usj}SLw`J@O1u-d!woLG9Cm#amce^u>guX z9au6i@X>26DpLVSv1D)-qQO;KDZ0U`)hKFTpeI{Xf4#FUd2-pLZ##Z9GHk@!`#*?kIrXT9dcqVyn9t=npTx8*b4z>lCubQKq~E;;>R z0KwK~L4rNKq+oZQ*Xp9s$J;znahsKrUw3{>Ltw{GbNfYW9Qzq-6p8S9I?-S&OCHXO zV=u;{FQYJNd*w@(0!#+5sXozzFJhG@C*dPwC2e)T_XWX1_gB-uKY!TslWJh?$}|`1;) zMizzt^YVK2dOP)%@cs5m*wSpr5AxXc--`G81DJ6ns1oN2T-{nUYc>*y_MBu>4F7!? zB4bL-d77bd?w{l^#>$g}9{qDGp~T8Li$Qe#)KNd%zfUOk(JW++_KWw){lx#210MJe z^#~tvmY3%9irjrixhS;bqXyCMe|4|Ud|bRZtWE zbpWU+QJe0|BrOp_@8#A^dPd53h^s@e%WxXRZ{v~u``zB}k(lfl#UEf3YBBm5?ZGM2 zvjzubpNTz{eO=Q_J?9F_q|(NF5|!w;PCjgYI40$`C|!#}c*OevgUbCU&4sJYB3zzb0m5IsC?=MQt)Cxu57|}v zR2bN`QjO2QrEnVPntivDBNOiV4$X$TEq^whwEy8%N9D)DAQQH%x>N4`o08GNnYM+U z#QMJcoNBq+1u*PmBG-!SssVt&MEF%&XuiG1nb9WYXhrmEdr&*V!7|TUfM$ek8%L)P z-@WBl!QR6O-P)QPXttt5Eq~ z0V_*G%RXsfkk>?2rpK!WxuoxamF&Yz0pjETWJo+i!p`ojI;5ziqG9e?`Z>k75Z&v@ z)%?%r@t$`rj6%W(Gw7zd?mN#?f1K5oN9pO#&F?%qhZ%Rbbjv@(%u{7-G&|>SJo8zy zuc&RxuIUS#3qAuL`!@08%A)1eSQP6Kx6c!N1Ir#l9S+z z`!ZS^Fs6m3-#lGPFDBCP9#nWm!!TKBDX6UWKtnXRS@?P?B zxr`t4iQE7QNanYQpOTz&kJpF*0vn7VyJEqh5I}h}FYxw>Zlz_Aj4^v;ey1@g9}-+> zU|KGD9qZzk?gNF+hP~S-5gI(pFe)mwpZ`=}-mtod22)WSes-#%snQky{jYO!jQRFj z88481jO1FBksM$W$O;HTgjh@5S5x!dxv7(xRRoi9#|1JS`UeKYM=xTCFLd_GLykgly!mSV&;v&W~n%_%N`(N+*0^?UNn_g z1Sp-_a)^Jko=l)IB67R3GJiY4uOvwEe%_8U$_AY+Rbt-Mc+1xKe=lo1iGQq>ij|7Oz$v zafF-t<~rC)+!)!+$Ln4uoAQ|o!FctX#Nrynwi~0zJu1%AmE_JI<`)Z(f&(XHBvd-b z34S$gX$HE(W>2@>Pi$E*4{r(Sz_>|c_a>CV$X%5c^WS!m{b35XMbm(#$cNtB*5US7 z8VbpY8fb~lGezcQd^X-hB1vu}b11wXvOy&I+Cd;c!m%SOMX2@mQn&Wye0?f7ym7MW zAeB8h^V}Y+ll|HBD)yN7YcIyuhCF;Wp5Jtc5%|@2qk=3oP(|2@GJCY+6`1vY3#

    XIv0;ZHC~W7$0w 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 E7b5R#ga7~l literal 0 HcmV?d00001 diff --git a/doc/source/_static/images/python.svg b/doc/source/_static/images/python.svg new file mode 100644 index 0000000..366f52f --- /dev/null +++ b/doc/source/_static/images/python.svg @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/doc/source/_static/images/rancher.svg b/doc/source/_static/images/rancher.svg new file mode 100644 index 0000000..e583873 --- /dev/null +++ b/doc/source/_static/images/rancher.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/doc/source/_static/images/terraform.svg b/doc/source/_static/images/terraform.svg new file mode 100644 index 0000000..4f76c26 --- /dev/null +++ b/doc/source/_static/images/terraform.svg @@ -0,0 +1 @@ +file_type_terraform \ No newline at end of file diff --git a/doc/source/_static/images/users.png b/doc/source/_static/images/users.png new file mode 100644 index 0000000000000000000000000000000000000000..5cb409b7a71e274836f840878ec3dd4ae381e2e0 GIT binary patch literal 5205 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 WZ^V#M#U0MiOE&usTHUfBpZg!_b5-d8 literal 0 HcmV?d00001 diff --git a/doc/source/_static/images/zookeeper.png b/doc/source/_static/images/zookeeper.png new file mode 100644 index 0000000000000000000000000000000000000000..16e0604aafc42ac9904ad9931a8c42c6ddbc8442 GIT binary patch literal 26639 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, +`security islands `_), but +usually introduces a problem of the so-called `Secret Zero +`_ +as a key to the key storage. + +Vault is an open-source software, provided and maintained by Hashicorp, that +addresses this very problem. It is considered one of the reference solutions +for it. This article demonstrates how to utilize infrastructure authorization +with Hashicorp Vault in an CCE-powered setup. As an example workload, we deploy +a Zookeeper cluster with enabled TLS protection. Certificates for Zookeeper are +stored in Vault, and they oblige required practices like rotations or audits. +Zookeper can easily be replaced by any other component that requires access to +internal credentials. + +Overview +======== + +.. graphviz:: dot/cce_vault_overview.dot + :layout: dot + +TLS secrets are kept in the Vault. They are being read by Vault Agent component +running as a sidecar in Zookeeper service pod and writes certificates onto the +file system. Zookeeper services reads certificates populated by Agent. Vault +Agent is configured to use password-less access to Vault. Further in the +document it is explained how exactly this is implemented. + +Establishing trust between CCE and Vault +======================================== + +Before any application managed by the CCE is able to login to Vault relying on +infrastructure based authentication it is required to do some steps on the +Vault side. Kubernetes auth plugin is enabled and configured to only access +requests from specific Kubernetes cluster by providing its Certificate +Authority. To allow several multiple different CCE clusters to use Vault, a +dedicated auth path is going to be used. + +.. code-block:: shell + + $ vault auth enable -path kubernetes_cce1 kubernetes + $ vault write auth/kubernetes_cce1/config \ + kubernetes_host="$K8S_HOST" \ + kubernetes_ca_cert="$SA_CA_CRT" + +Since in our example a dedicated service account with token is being +periodically rotated using `client JWT as reviewer JWT +`_ +can be used. + +Access rules for Vault +====================== + +Having Auth plugin enabled, as described above, CCE workloads are able to +authenticate to Vault, but they can do nothing. It is now necessary to +establish further level of authorization and let particular service accounts of +CCE to get access to secrets in Vault. + +For the scope of the use case, we grant the Zookeeper service account from its +namespace access to the TLS secrets stored in Vault's key-value store. For that +a policy providing a read-only access to the /tls/zk* and /tls/ca paths is +created. + +.. code-block:: shell + + $ vault policy write tls-zk-ro - <`_ + +* Use `PKI secrets engine `_ to + issue certificates + +Vault enables users not only to store TLS certificates data in the key-value store, +but also to create and revoke them. To keep this tutorial simple enough we are +not going to do this and just upload generated certificates into the KV store. +For production setups this example can be easily extended with extra actions. + +.. code-block:: shell + + $ vault kv put secret/tls/ca certificate=@ca.crt + $ vault kv put secret/tls/zk_server certificate=@zk_server.crt private_key=@zk_server.key + $ vault kv put secret/tls/zk_client certificate=@zk_client.crt private_key=@zk_client.key + +Certificate paths and property names used here are referenced by the Zookeeper installation. + +Deploying Zookeeper +=================== + +Now that the secrets are stored safely in Vault and only allowed applications +can fetch them it is time to look how exactly the application accesses the +secrets. Generally, utilizing Vault requires modification of the application. +`Vault agent `_ is a tool that was +created to simplify secrets delivery for applications when it is hard or +difficult to change the application itself. The Agent is taking care of reading +secrets from Vault and can deliver them to the file system. + +There are many way how to properly implement Zookeeper service on the +Kubernetes. The scope of the blueprint is not Zookeeper itself, but +demostrating how an application can be supplied by required certificates. The +reference architecture described here bases on the best practices gathered from +various sources and extended by HashiCorp Vault. It overrides default Zookeeper +start scripts in order to allow better control of the runtime settings and +properly fill all required configuration options for TLS to work. Other methods +of deploying Zookeeper can be easily used here instead. + +1. Create a Kubernetes namespace named `zookeeper`. + +.. code-block:: shell + + $ kubectl create namespace zookeeper + +2. Create a Kubernetes service account named `zookeeper`. + +.. code-block:: shell + + $ kubectl create serviceaccount zookeeper + +3. In Kubernetes a *service account* provides an identity for the services + running in the pod so that the process can access Kubernetes API. The same + identity can be used to access Vault, but require one special permission - + access to the tokenreview API of the Kubernetes. When instead a dedicated + reviewer JWT is used, this step is not necessary, but it also means + long-living sensitive data is used and frequently transferred over the + network. More details on various ways to use Kubernetes tokens to authorize + to Vault `can be found here + `_. + +.. code-block:: shell + + $ kubectl create clusterrolebinding vault-client-auth-delegator \ + --clusterrole=system:auth-delegator \ + --serviceaccount=zookeeper:zookeeper + +4. Create a Kubernetes ConfigMap with all required configurations. One possible + approach is to define dedicated health and readiness check scripts and to + override automatically created Zookeeper start script. This is especially + useful when TLS protection is enabled, but default container scripts do not + support this. + +.. code-block:: yaml + :caption: zookeeper-cm.yaml + + --- + apiVersion: v1 + kind: ConfigMap + metadata: + name: zookeeper-config + namespace: "zookeeper" + data: + ok: | + #!/bin/sh + # This sript is used by live-check of Kubernetes pod + if [ -f /tls/ca.pem ]; then + echo "srvr" | openssl s_client -CAfile /tls/ca.pem -cert /tls/client/tls.crt \ + -key /tls/client/tls.key -connect 127.0.0.1:${1:-2281} -quiet -ign_eof 2>/dev/null | grep Mode + + else + zkServer.sh status + fi + + ready: | + #!/bin/sh + # This sript is used by readiness-check of Kubernetes pod + if [ -f /tls/ca.pem ]; then + echo "ruok" | openssl s_client -CAfile /tls/ca.pem -cert /tls/client/tls.crt \ + -key /tls/client/tls.key -connect 127.0.0.1:${1:-2281} -quiet -ign_eof 2>/dev/null + else + echo ruok | nc 127.0.0.1 ${1:-2181} + fi + + run: | + #!/bin/bash + # This is the main starting script + set -a + ROOT=$(echo /apache-zookeeper-*) + ZK_USER=${ZK_USER:-"zookeeper"} + ZK_LOG_LEVEL=${ZK_LOG_LEVEL:-"INFO"} + ZK_DATA_DIR=${ZK_DATA_DIR:-"/data"} + ZK_DATA_LOG_DIR=${ZK_DATA_LOG_DIR:-"/data/log"} + ZK_CONF_DIR=${ZK_CONF_DIR:-"/conf"} + ZK_CLIENT_PORT=${ZK_CLIENT_PORT:-2181} + ZK_SSL_CLIENT_PORT=${ZK_SSL_CLIENT_PORT:-2281} + ZK_SERVER_PORT=${ZK_SERVER_PORT:-2888} + ZK_ELECTION_PORT=${ZK_ELECTION_PORT:-3888} + ID_FILE="$ZK_DATA_DIR/myid" + ZK_CONFIG_FILE="$ZK_CONF_DIR/zoo.cfg" + LOG4J_PROPERTIES="$ZK_CONF_DIR/log4j.properties" + HOST=$(hostname) + DOMAIN=`hostname -d` + APPJAR=$(echo $ROOT/*jar) + CLASSPATH="${ROOT}/lib/*:${APPJAR}:${ZK_CONF_DIR}:" + if [[ $HOST =~ (.*)-([0-9]+)$ ]]; then + NAME=${BASH_REMATCH[1]} + ORD=${BASH_REMATCH[2]} + MY_ID=$((ORD+1)) + else + echo "Failed to extract ordinal from hostname $HOST" + exit 1 + fi + mkdir -p $ZK_DATA_DIR + mkdir -p $ZK_DATA_LOG_DIR + echo $MY_ID >> $ID_FILE + + echo "dataDir=$ZK_DATA_DIR" >> $ZK_CONFIG_FILE + echo "dataLogDir=$ZK_DATA_LOG_DIR" >> $ZK_CONFIG_FILE + echo "4lw.commands.whitelist=*" >> $ZK_CONFIG_FILE + # Client TLS configuration + if [[ -f /tls/ca.pem ]]; then + echo "secureClientPort=$ZK_SSL_CLIENT_PORT" >> $ZK_CONFIG_FILE + echo "ssl.keyStore.location=/tls/client/client.pem" >> $ZK_CONFIG_FILE + echo "ssl.trustStore.location=/tls/ca.pem" >> $ZK_CONFIG_FILE + else + echo "clientPort=$ZK_CLIENT_PORT" >> $ZK_CONFIG_FILE + fi + # Server TLS configuration + if [[ -f /tls/ca.pem ]]; then + echo "serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory" >> $ZK_CONFIG_FILE + echo "sslQuorum=true" >> $ZK_CONFIG_FILE + echo "ssl.quorum.keyStore.location=/tls/server/server.pem" >> $ZK_CONFIG_FILE + echo "ssl.quorum.trustStore.location=/tls/ca.pem" >> $ZK_CONFIG_FILE + fi + for (( i=1; i<=$ZK_REPLICAS; i++ )) + do + echo "server.$i=$NAME-$((i-1)).$DOMAIN:$ZK_SERVER_PORT:$ZK_ELECTION_PORT" >> $ZK_CONFIG_FILE + done + rm -f $LOG4J_PROPERTIES + echo "zookeeper.root.logger=$ZK_LOG_LEVEL, CONSOLE" >> $LOG4J_PROPERTIES + echo "zookeeper.console.threshold=$ZK_LOG_LEVEL" >> $LOG4J_PROPERTIES + echo "zookeeper.log.threshold=$ZK_LOG_LEVEL" >> $LOG4J_PROPERTIES + echo "zookeeper.log.dir=$ZK_DATA_LOG_DIR" >> $LOG4J_PROPERTIES + echo "zookeeper.log.file=zookeeper.log" >> $LOG4J_PROPERTIES + echo "zookeeper.log.maxfilesize=256MB" >> $LOG4J_PROPERTIES + echo "zookeeper.log.maxbackupindex=10" >> $LOG4J_PROPERTIES + echo "zookeeper.tracelog.dir=$ZK_DATA_LOG_DIR" >> $LOG4J_PROPERTIES + echo "zookeeper.tracelog.file=zookeeper_trace.log" >> $LOG4J_PROPERTIES + echo "log4j.rootLogger=\${zookeeper.root.logger}" >> $LOG4J_PROPERTIES + echo "log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender" >> $LOG4J_PROPERTIES + echo "log4j.appender.CONSOLE.Threshold=\${zookeeper.console.threshold}" >> $LOG4J_PROPERTIES + echo "log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout" >> $LOG4J_PROPERTIES + echo "log4j.appender.CONSOLE.layout.ConversionPattern=\ + %d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n" >> $LOG4J_PROPERTIES + if [ -n "$JMXDISABLE" ] + then + MAIN=org.apache.zookeeper.server.quorum.QuorumPeerMain + else + MAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=$JMXPORT \ + -Dcom.sun.management.jmxremote.authenticate=$JMXAUTH \ + -Dcom.sun.management.jmxremote.ssl=$JMXSSL \ + -Dzookeeper.jmx.log4j.disable=$JMXLOG4J \ + org.apache.zookeeper.server.quorum.QuorumPeerMain" + fi + set -x + exec java -cp "$CLASSPATH" $JVMFLAGS $MAIN $ZK_CONFIG_FILE + + vault-agent-config.hcl: | + exit_after_auth = true + pid_file = "/home/vault/pidfile" + auto_auth { + method "kubernetes" { + mount_path = "auth/kubernetes_cce1" + config = { + role = "zookeeper" + token_path = "/run/secrets/tokens/vault-token" + } + } + sink "file" { + config = { + path = "/home/vault/.vault-token" + } + } + } + + cache { + use_auto_auth_token = true + } + + # ZK is neat-picky on cert file extensions + template { + destination = "/tls/ca.pem" + contents = <` with the address of the + Vault server. This includes a pod with Vault Agent side container as an init + container, Vault Agent side container used continuously in the run cycle of + the pod and Zookeeper main container. + +.. code-block:: yaml + :caption: zookeeper-ss.yaml + + apiVersion: apps/v1 + kind: StatefulSet + spec: + podManagementPolicy: Parallel + replicas: 3 + selector: + matchLabels: + app: zookeeper + component: server + serviceName: zookeeper-headless + template: + metadata: + labels: + app: zookeeper + component: server + spec: + containers: + + - args: + - agent + - -config=/etc/vault/vault-agent-config.hcl + - -log-level=debug + - -exit-after-auth=false + env: + - name: VAULT_ADDR + value: + image: vault:1.9.0 + name: vault-agent-sidecar + volumeMounts: + - mountPath: /etc/vault + name: vault-agent-config + - mountPath: /tls + name: cert-data + - mountPath: /var/run/secrets/tokens + name: k8-tokens + + - command: + - /bin/bash + - -xec + - /config-scripts/run + env: + - name: ZK_REPLICAS + value: "3" + - name: ZOO_PORT + value: "2181" + - name: ZOO_STANDALONE_ENABLED + value: "false" + - name: ZOO_TICK_TIME + value: "2000" + image: zookeeper:3.7.0 + livenessProbe: + exec: + command: + - sh + - /config-scripts/ok + failureThreshold: 2 + initialDelaySeconds: 20 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 5 + name: zookeeper + ports: + - containerPort: 2281 + name: client + protocol: TCP + - containerPort: 2888 + name: server + protocol: TCP + - containerPort: 3888 + name: election + protocol: TCP + readinessProbe: + exec: + command: + - sh + - /config-scripts/ready + failureThreshold: 2 + initialDelaySeconds: 20 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 5 + securityContext: + runAsUser: 1000 + volumeMounts: + - mountPath: /data + name: datadir + - mountPath: /tls + name: cert-data + - mountPath: /config-scripts + name: zookeeper-config + dnsPolicy: ClusterFirst + + initContainers: + - args: + - agent + - -config=/etc/vault/vault-agent-config.hcl + - -log-level=debug + - -exit-after-auth=true + env: + - name: VAULT_ADDR + value: + image: vault:1.9.0 + name: vault-agent + volumeMounts: + - mountPath: /etc/vault + name: vault-agent-config + - mountPath: /tls + name: cert-data + - mountPath: /var/run/secrets/tokens + name: k8-tokens + restartPolicy: Always + serviceAccount: zookeeper + serviceAccountName: zookeeper + terminationGracePeriodSeconds: 1800 + volumes: + - configMap: + defaultMode: 420 + items: + - key: vault-agent-config.hcl + path: vault-agent-config.hcl + name: zookeeper-config + name: vault-agent-config + - configMap: + defaultMode: 365 + name: zookeeper-config + name: zookeeper-config + - emptyDir: {} + name: cert-data + - name: k8-tokens + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + expirationSeconds: 7200 + path: vault-token + + updateStrategy: + type: RollingUpdate + volumeClaimTemplates: + - apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: datadir + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: csi-disk + volumeMode: Filesystem + +.. code-block:: bash + + $ kubectl apply -f zookeeper-ss.yaml + +With this a production-ready Zookeeper service with enabled TLS has been +deployed sucessfully to the CCE. The Vault Agent takes care of authorizing to +HashiCorp Vault using a Kubernetes service account with a short time to live +token and fetches required secrets to the file system. In the entire Kubernetes +deployment there are no secrets for the application, neither the key to the +Vault, nor TLS certificates themselves. Not even using Kubernetes secrets is +necessary. + +References +========== + +* https://learn.hashicorp.com/tutorials/vault/agent-kubernetes?in=vault/app-integration + +* https://learn.hashicorp.com/tutorials/vault/agent-kubernetes?in=vault/auth-methods + +* https://www.vaultproject.io/docs/auth/kubernetes diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 0000000..0f8819a --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# +# -- General configuration ------------------------------------------------ + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. + +extensions = [ + 'sphinx.ext.graphviz', + 'otcdocstheme', +] + +# openstackdocstheme options +otcdocs_repo_name = 'opentelekomcloud-blueprints/docs' + +# The suffix of source filenames. +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +copyright = u'2017-2021, OpenTelekomCloud Contributors' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'otcdocs' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +otcdocs_auto_version = False + +html_favicon = '_static/favicon.ico' + +# To use the API Reference sidebar dropdown menu, +# uncomment the html_theme_options parameter. The theme +# variable, sidebar_dropdown, should be set to `api_ref`. +# Otherwise, the list of links for the User and Ops docs +# appear in the sidebar dropdown menu. +html_theme_options = { + 'show_other_versions': False, + 'sidebar_mode': 'toctree', +} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +html_css_files = [ + 'css/default.css' +] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'native' + +templates_path = ['templates'] + +graphviz_output_format = 'svg' + +# -- Options for LaTeX output --------------------------------------------- + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'os-doc-blueprints.tex', u'os-doc-blueprints Documentation', + u'OpenTelekomCloud Contributors', 'manual'), +] diff --git a/doc/source/dot/cce_vault_overview.dot b/doc/source/dot/cce_vault_overview.dot new file mode 100644 index 0000000..335d37e --- /dev/null +++ b/doc/source/dot/cce_vault_overview.dot @@ -0,0 +1,23 @@ +digraph cce_vault { + graph [bgcolor=transparent compound=true fontcolor="#2D3436" + fontname="Sans-Serif" fontsize=10 rankdir="RL"] + node [fixedsize=false] + subgraph cluster_cce { + graph [bgcolor="#E5F5FD" shape=box style=rounded label="CCE" rankdir="LR"] + zk_svc [label="ZK Service" fixedsize=True fontsize=10 height=1.4 + image="../_static/images/k8_svc.png" imagescale="true" labelloc=b + shape=none width=1 rank="min"] + zk_pod1 [label="ZK Pod" fixedsize=True fontsize=10 height=1.4 image="../_static/images/k8_pod.png" imagescale="true" labelloc=b shape=none width=1 rank="same"] + zk_pod2 [label="ZK Pod" fixedsize=True fontsize=10 height=1.4 image="../_static/images/k8_pod.png" imagescale="true" labelloc=b shape=none width=1 rank="same"] + zk_pod3 [label="ZK Pod" fixedsize=True fontsize=10 height=1.4 image="../_static/images/k8_pod.png" imagescale="true" labelloc=b shape=none width=1 rank="same"] + zk_pod1 -> zk_svc + zk_pod2 -> zk_svc + zk_pod3 -> zk_svc + } + vault -> zk_pod1 + vault -> zk_pod2 + vault -> zk_pod3 + vault [label="Vault" fixedsize=True fontsize=10 height=1.4 image="../_static/images/vault.png" imagescale="true" labelloc=b shape=none width=1] + user [label=Clients fixedsize=true fontsize=10 height=1.4 image="../_static/images/users.png" imagescale=true labelloc=b shape=none width=1] + zk_svc -> user [dir=both] +} diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 0000000..32eee9c --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,15 @@ +Blueprints +========== + +Users sometimes identify use cases that can be solved in a standardized way to +save research time and effort. Blueprints are a series of best practices, +curated by the Open Telekom Cloud engineering and architecture teams. While +they are not covered directly by the `Service description +`_, they are tested and +validated recommendations from our experts. + + +.. toctree:: + :maxdepth: 1 + + cce_vault.rst diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..608098c --- /dev/null +++ b/setup.cfg @@ -0,0 +1,21 @@ +[metadata] +name = blueprints +summary = OpenTelekomCloud Blueprints docs +author = Artem Goncharov +author_email = artem.goncharov@gmail.com +home_page = https://cloud.otc.com +python_requires = >= 3.6 +classifier = + Environment :: OpenStack + Environment :: Other Environment + Intended Audience :: Information Technology + Intended Audience :: System Administrators + License :: OSI Approved :: Apache Software License + Operating System :: POSIX :: Linux + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Topic :: Documentation diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..6345380 --- /dev/null +++ b/setup.py @@ -0,0 +1,18 @@ +# 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 setuptools + +setuptools.setup( + setup_requires=['pbr>=2.0.0'], + pbr=True) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..966a2db --- /dev/null +++ b/tox.ini @@ -0,0 +1,26 @@ +[tox] +minversion = 3.6.0 +envlist = docs +ignore_basepython_conflict = true + +[testenv] +basepython = python3 +usedevelop = true +deps = + # -c{env:TOX_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/upper-constraints.txt} + -r{toxinidir}/doc/requirements.txt +sitepackages = False +whitelist_externals = + rm + +[testenv:venv] +commands = {posargs} + +[testenv:docs] +deps = + -r{toxinidir}/doc/requirements.txt + pre-commit +commands = + # pre-commit run -a + rm -rf doc/build/hml doc/build/doctrees + sphinx-build -a -E -W -d doc/build/doctrees -b html doc/source doc/build/html