From 74ee1100967163f1a5e5406740f4150d2e190cf7 Mon Sep 17 00:00:00 2001 From: Justin Barksdale Date: Fri, 24 May 2024 10:57:52 -0400 Subject: [PATCH 01/22] Created Crossplane 1.16, Deprecated 1.7 --- packs/crossplane-1.16/README-template.md | 34 +++ .../charts/crossplane-1.16.0.tgz | Bin 0 -> 13656 bytes packs/crossplane-1.16/charts/values.yaml | 186 +++++++++++++++++ packs/crossplane-1.16/logo.png | Bin 0 -> 91169 bytes packs/crossplane-1.16/pack.json | 28 +++ packs/crossplane-1.16/presets.yaml | 53 +++++ packs/crossplane-1.16/schema.yaml | 0 packs/crossplane-1.16/values.yaml | 193 ++++++++++++++++++ packs/crossplane-1.7.0/pack.json | 3 +- 9 files changed, 496 insertions(+), 1 deletion(-) create mode 100644 packs/crossplane-1.16/README-template.md create mode 100644 packs/crossplane-1.16/charts/crossplane-1.16.0.tgz create mode 100644 packs/crossplane-1.16/charts/values.yaml create mode 100644 packs/crossplane-1.16/logo.png create mode 100644 packs/crossplane-1.16/pack.json create mode 100644 packs/crossplane-1.16/presets.yaml create mode 100644 packs/crossplane-1.16/schema.yaml create mode 100644 packs/crossplane-1.16/values.yaml diff --git a/packs/crossplane-1.16/README-template.md b/packs/crossplane-1.16/README-template.md new file mode 100644 index 00000000..56ba8119 --- /dev/null +++ b/packs/crossplane-1.16/README-template.md @@ -0,0 +1,34 @@ +# Crossplane + +Crossplane is an open source Kubernetes extension that transforms your Kubernetes cluster into a universal control plane. + +Crossplane lets you manage anything, anywhere, all through standard Kubernetes APIs. Crossplane can even let you order a pizza directly from Kubernetes. If it has an API, Crossplane can connect to it. + +With Crossplane, platform teams can create new abstractions and custom APIs with the full power of Kubernetes policies, namespaces, role based access controls and more. Crossplane brings all your non-Kubernetes resources under one roof. + +Custom APIs, created by platform teams, allow security and compliance enforcement across resources or clouds, without exposing any complexity to the developers. A single API call can create multiple resources, in multiple clouds and use Kubernetes as the control plane for everything. + +## Prerequisites + +Kuberernetes >= 1.27.0 +## Usage + +Installing a provider creates new Kubernetes resources representing the Provider’s APIs. Installing a provider also creates a Provider pod that’s responsible for reconciling the Provider’s APIs into the Kubernetes cluster. Providers constantly watch the state of the desired managed resources and create any external resources that are missing. + +Install a Provider with a Crossplane Provider object setting the spec.package value to the location of the provider package. + +*For Example* +Install the [Palette Provider](https://marketplace.upbound.io/providers/crossplane-contrib/provider-palette/v0.19.2) + +```yaml +apiVersion: pkg.crossplane.io/v1 +kind: Provider +metadata: + name: provider-palette +spec: + package: xpkg.upbound.io/crossplane-contrib/provider-palette:v0.19.2 +``` +## References + +Crossplane Provider Guide - https://docs.crossplane.io/latest/concepts/providers/ +Crossplane Concepts - https://docs.crossplane.io/latest/concepts/ \ No newline at end of file diff --git a/packs/crossplane-1.16/charts/crossplane-1.16.0.tgz b/packs/crossplane-1.16/charts/crossplane-1.16.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..d0ff023a54ddec3d21e4820f64f66d99bd66879e GIT binary patch literal 13656 zcmV-eHK)oSiwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0PKB#bKEwP=>E-5fs^;@?A#1Bl4UtNce#3sByaR$%PL7uHkC?w zFl5gRP9(tqpyY||_t{^e0g&L2`6bJ;H!J>OYe=BcXmmHa8x0^5T*^G58EhZUs8HdY zrpaIK_8ANYgZ;fd{C_YQH2>e(-P!%i&ffm+&hFmx-QB@o20KrmKHdKd8Qd`*olhYZ z6@M9ga$C*L{gXU2XFq|EjAuh~y%W$pFMsZYJNw}vh(Shz&mh3{9Bs3#Dhm1&G zhzQ7!#TY~e3M8R%+~*llGpYz=bew=Bc|z5Mi!>la0Zk=QoKPtt9Vb9oHW5@RQADZ` zKqi8xBrOuf@&w2=WHA@AM`#ukc$aetWX7g55F~+XNCHA6B$K`bam^wi2WKaeOt>I4 z&l46=jeFH*#4}l>5C$`z!jR0A%H?o-yOM;E@qk6TyY5@eBN^5TY||_joW=cUCU^?{ zoxknA+xgpWm}k@A3g$Ol#Bvz)NtEy+4*HG$1$|<1l|kRfGU$_-Dmtc8mx*XJ)Blf) z=n9mBVrm3^!gF1F8tK339|kPFL5K+((=m1J%ioirPeiOg$)~Qg*ASIC6*L}ea98-^ zN|%Kz8KjhDin0s@_6JhRlA%U~|DQU=2+63Xr^h0%s=9&sSXBwG8+`VqCE;K5@$~;S zO$v~oVFFmL|9AGD?LBSk|NX)92mOB^&m%H}B<*VjM+9Us2uaioB#?-wDP&3#mMKnB zDz0LFlZE7sgz}eGvME)HWm9r90|CJ!t(yeT8C4JlkAg>}-zS$dAX$-)K@dLi6-3Ts zG7^C5PmZ*5jv-I@JPh2+A=wEkAm*z^i%2D?g6SOfyqbXzR!-ya;3S2Uwj5V{>1 z2373~TX{&%d6KYf`X-O5f*@ciox(661e-jEoJ*#-=xjwJkLAOF5K$H#l6U#lG%WHl zFS1xq6`qWF`p>p;SqF*$iK5ex9KnPZiNZNcH;wYC2{@`|=@DTW8C90sNaLdDbV#rgSF7npu;Llk8OarFa4YC&aZNdBun1*WWxqbTVNXQw-LEV@uBw8w2GSjTbVSaj8y0 z-EeU=>S6{D3^}BQv6j&C(XvsmJ{45URRh8qj|q(;kmZ2uN+dJ2aB`J7jUXh4Jd-R2 zK_nQ_8^xJ4!-KsX9VUfTAYL#b)z3`LelV?%w8>NAF(eb3NU;69$RT2rIkwvXHwMEj z<9P@D!k{dSJXg^^Dx~5m86|WK$y($$HC|$QZwP!~G|RYJpD|3egQ}7NYi+NCDB?w? zN^#$yp^F*>Eg}n=@|oz@1gIW1OWFYh%geMF1 zQW%(m$F|&%C{aL*oK#E;qvJbC83t5LjYI{x;MbbxDq@j@Nu|}%nf*j^8eP#TAT*Xq zMUw=Thkb1TMLe6ZX<@{*1KOegeLawqB8wJ4dtpCy0cydiYs<4DNiHA~pp5LHyAsE1 zFhirdg)U&qq!RN(`hAhb37C!!Yx4lUdPQ?=Q9CNyde#z7-H;s~kTF)*co@%$Oh835 zU8?LPx=*%229n$`H6ulKmFYQ~3sPiCXcZBY2!vu2?R@}hdSj;7CyxrPE0})~tggUn z7c03X)f~6zxvP{sf}STh7mM)m|3aif@;XcA7Q0xRD;c?g@r?5;8M?RM89`Yn&aOg< zfE8``zH3Ic>;`dLQgq*J(^fs zf5o&ujS8eN&lJ2jOR^l$>clRw~HUPdq77I7}!@H9-mqn$#Vb z9WiMF$_gU_=p;ADHi9%)^CKok#DGPk@j7afp~9oGaXw4ikpth*U|Q*Uv;9UYtZUX; zOHr%^$0>?uJG-~jVz)+bO-Rc%S%a`kRaqDOjg{F#AfKkrI!%ks6k2Nn|3sCRf)Xrh znZRd)r=Vs~NRm@E>yexbg)_U11kLLfy0?&n#l9VUJHS4VxtgtM9eAd*AIb0xHOQ`+ z;F(s1G$GeiFe|((0|$@DIphhAK%+V*qi|$Yv4deW2RbmLx1*4};DW$An&t`g$mrtW z)!EDA@WROFEX_jL{qX8 z?4=1=P%&moP%-zHXkVjOEJ<7l{OYT9tYu6JmX&!}obA{!F@5518?M$_SNXZPvev;F7a{%vQlGt_0aEmM2IW{{+zoNa3_en@gIRlf=o z=|VDxsA|2@xP zJ$+dJyN~A_5};D+jQ64aJJg=`$B#jP%Sy!f-S6LrW|hf)G~bT=+>o+}_qHrqYK^j# zeN&b=@NzZUr4Py_FO8X2WA#Ebr(>32Me^ zy(lIV_Ks}zD`1et__smvPykgHC4;2K*k&4OH^=wbOetKRT#h~#teVUP%hZHy{k!b{ zyWFaGqo&%(2aIjg2*}odZjr6GTes-a-ys8`J2j?~MFw5D6kStfi+ubTII9MGpcN%y zS(FrUXa7Q7gXVd7RT_!fs7ulEjr-#{0w`w*yXw_lDdK6)Gsx7?WT5ry`ET07vqoV@ z<(vxD=M!wsDWwj6T7Yk6=c~@HF0F|MUlu{VpE$6V+H68v^HDdf>uPf9sPcjQUT{@{ z)g$h;U}eEy4mY2P;=j-|SyG|~%l>Kj=*Te2@jC?~qjqWXLU94dcJ1p0P|Ur2kPgKcJ~|e|Nj2oL;l~rJibFO#xx3Pp=MmLKhO{luf8?f zY$veJe6{);_#S+zbXVzXVrMWDMy7ebW-UTcsdT7xH{FHg17TSVnId}~+SFTD4^2!A z6}Mg2W;{DD5?rB)sxFpGwfcRZq*O(-mmd1WkgSmy?v~2?iuWTgDzl{(+g8x;_k(+; z`p^b&7oc{JgMv!{HFC*_=bAVM#jW6$RQ2XNQ6zx5>NIBeY3S*H_epWs67RR|0hhEKW@q{-j)R2ZKIt?O?H&@->uV~I#run4*KmVq~GDz zmj-US#nmWO?OTj;*#=d`*;kQyP2yG~(oN<*i8vQA%Y2>D!EYE#O=)hBN1OIjF}ztV z3vtS%CYeq5T8`s2O;}77%ceGus+J^Z5KjxWw8WkE=S$DZ_xG%_|HdqfSvLJ7GjLV> z_xWI_ZvX8LcAh`Pf9~bEy(RL!;f$}{4Ae|~4invw(@{%$8kDP6p2@XAzhq&T%!0lJ zR8J1xj7DY7e>)<9ugRx-zn${$tr_3NZm{L@zdP7}+Km71@9jUx|Ghj~oc_8bphJe= zb&A{47?74h_}!Z37^CskjJBUDjdE1-+HEz-I#P0beIu#`vUW`Hb}o>vfk_tiIG&em zZpzVG_IVZkBOgfChG@MXw@zJURcpkZ6Kr3aTGAyIn|!Lace@FlR#M7s*fYS@Jck-; z?ag_nnrqu4>9I&j{0ZTrgk!Ul%8dRMH15bRaBwX_YYi=Gr7TBCUgklWShkuC$+j)O zs1O%wNVdKmd^^}$P{ia=mG15mEZ57ZcV2KyR;J7tCAf#?w(Y%EBb2(3mUI)Z#!LIlVT!_zeCW&#Cu;AW*Jk5 zygDDiQLJyaPz}kJ2f^%>tv1S%j~|Dv&x%gThjNMVv0H1q_Ey@eb(AOMc}(})H-&S zcmlt(+a_C0&n(sKV5GG>TriP13irLqE#qn*GzITBwIUM-F-QJ_44G^$>mqp7n6>@ zX?M%%dFyX`drw;mH<7S{mdB?D-@iOQ>V}D{?`zE=Y_i;!>_+1F;^OV)%M0w? z@%h_}vqC08L*mOxF9hOm- zVU%%oTTAy2th3K5L4RvU)8Yc-Q$#*EUH!(S!&zeM&kO5&})9gTgG2ZCJTQvi>S5GwFan;^xh1<51%EMAu&~dK-eSN%mr;)~U~y>#}Y& zw!i)om4C`qRj6_HRBH!Ht=6rU#=O(0sxq}Bs@kpkb#B#JcW9Nj23#Fu)oQLRy?zI4 zK4N)7W>v;JG*dHwC$xLX|LDyBLB8snWApCdK;Qb{*UK_y@&Jv@8x;_-dead zo#M`h`1ldGD`=6(6Y|)}#S`*ZyCLm9S@q%h3{R*0i!qJ*X5Xji<7q<>m#f|V9E45o zUQ;)$lK=f@4f)^Q+k5tq|93CXTDzpa#FnLHYeQb{bvvIe;?0!yCm;d_WM5n-RD+;FSK#63w{~aUvJZ11LmS_YD+e% zRlq&)RRfRk3y%?^z1t|XL5!1KJ_q0e{%HJ;`NG@4aiAxseoAVUL9f?u2pbKp6i z3K5gX%$(uPZ!!=>zyt(j5fBNPgeUF@kLpr{E(9}xSdvPi62_Vt{Z##EiI_)nyQIjrxig}#MKZ&G|JW|Ud*^J(?MFz&qn_LEe``& zx&ME^vHy2>_u1~?!T-OH=QI2NpK?gR7YhU2=ZOLJPOg1?K!Y^vY=Q0$BCeMIPd^M` zx%}@8_I92%&;NM-{2~5#FVDvEf2X_mnU{`m^op_lE8B?D20C@L|Kh%VB!h z@V^$jd_BAWy$e15*|z`RZufu3XmoGg|0;HhX>7fpwf(nuysfLgxp(8eT|Of%+q|=E z%TOmX{<-%IJ!}tO(w(n#`({HZ*WJG9TPC;N%ITlA;fEu>`}8yt^L#aXMc36QYZ@lq z8$0i0=jDS&d)NiJeor>s0O%`?C7S^^+n%+6EAMH4))GJacA57JA>7JB^`YG+BY#o- zTV?0h=8TOp^*d{>BFMk=^1=~G^@{J>R@J!;A?wxy<}zZ!$H zna=y{Q?W_Me^k2)USnV`6yZW*s+CK@Qk-a(x0(52EpLhZy0!INEjx+)YRdgqCL@tw zr=WV6hSW1TM!zj>J1wMgS%@yWq<`xUFq*h4XnJ@BWlHD4Bg}l%cnY8~;ev2A198J7 z5SA$rG*Tw667ejv{;s>ohFs2Ij(KM^ksKifkGwocF5Ie?mleMT6-q3tN{p(!gxPJk@R>n=;;E zBPpK5FfOK;E8iTHu8h{!cr40iUCvlvT(x%?h8r1QUqZ2K1nymT}@R>Ni)?=*)`aDbK_s#Yl^Uo*Bz*jh_2^2|GAfEbzRi8 z^8Dq-zf=AV-gk2M<6l?LF4?lXV3N@?*G4+=l%WM|G4JuAllG0+ie9<$upv6 zOcExoa~_-1TG0@hFx;1J4^v;M>e1b2mkX|!N zet;x3RuH+NbF^eY8$Ok76+F_g&A!vP=hv@Z6RKNJl5mmU)a5($Wyi%P>*!3gvEp@3 ze=opSF8|WB?7YNfV`@H-u;WzR2P%F770UyFH>Kj|(*FzQe>Cmx$^cj~|L^QPf8Lz` zpYJ{F|GbxHjazhd}`0i z^FLbm|381a^Wgv8%X7QX&R1|R{~c`4ukVz-)7|=CGQ6~rZuR6poI#SZX~xAJTbrxo z|Jn1MhWtN$_H6e-{_o>?M9!#EATnGRGNW&naK;5oVwO$aJwo>MOD2gda-9E(oI#S1 zX~M@QoswnKp0*sQV%LCoyLj(u7GnyWNzf#Za{&|f4q_uG|Mny#ud`%Mc!o7KN+btC z5|%+2ghv-|F!UZgtF(uuj!rHv&riO8gZoT1fSr&WRjGSnV6oYA9(ViC{hf=y@29>U56flM(qCoUBO+jAQ>J8ED$E|VsoRjYPYjjV?N zOld-n5p)ZQBGVnTQ8pSO6o*9?6PhFzj7jUoPt0Wk+v84q&BJBK^ByKJ3k@H0?@%*) z2OmFwH$CaMq3uj7IsCF$Lxuz%5OmQ^h5%Y(nzq( z{N2Mm30g>uFj^?)6H-9f_#++|%O^w@(aa*&(-SCme>^wXQ-tkP=7wo*;(|P8?1>p3 zIb*qoG+`4p*K=Q_K|g*r`1dE+oSvBt;T@ntNkuU=SPzo`=^(NvWDFThSj1>jhwkB7 z4f!v;*dmX)z`w-S6MxichBUcmaiL)e;`4_E0PjFVOro_=ov&c{%*At=Y_r-0CU$IT z@k*PVmg7;l0%G%Zf)u~fO{6?#6BZep+zqht1@vc^@rXOtO~Sq86Lq86%O#@l7<#4b zAs`FJ6zDnmpRj3R_A(p$phDeTk<><=W^?mSfGiS}kBQ(ZNgMr3b3!OFxMC5M>dm@^u}K9dR4F~TAcY*Z7Q|zk5qL+_JON$N=Kf+uUGgB$A&c2N zGKPfTJgKN~1cF@~D_0XlZZ$bTx6w@l+j|Si(7+)+rcw`HhN2kjHZ=DOo*G@Hn=;EJ zT-a2{N*S2^TP^P8G0#2UckK~K=$H%l%jGQBrOEAtf?R-vOd<6txtZ|p8+6Rdo?uQWpY*&rvLtE?DNP;VlWNotwJNuBeCLQaWuO#Uuf39hR^Z%RTH>LB z)y4#QIF6Y=K-ep)Of4=JBH#0bLTRnfGnyn$ZOdYuGG&#AvpbNx5OYM&iUKxd*X0^! zg&Sp@?v~CLzM-PEGB&UIeGD_2ObDMWHeS}7?a5ZzCwESWneR)r%qIkc;(})^>R~1! zO^}angszvN@lj-!`b1V2c3M^{38m?zWF;&}f7x3)6_vWnZ-ZwZP9&u)(UlV>mF)Rb zR%r^!xm1u!UxhO%3(!+Ygma`VVTNDNeD)XzXKVRH?|EvZ#swa=HQiz+qe9{=k1eLC zFRdB*GitnQYJzu;2=%@?evEh~a~2i6kjb2+R9r!QBZV`$K(c9ux}Rk@Mo8FBPSnb3 z>y#@(i7%_+R$GJ{_I259CxI(X9-n|(Kcu!i0cp z9^rPt=4@{LKeJKNcw5lZ=3uV*xTWbTb)FaFghk0*GisjDd9QktgD_LA#5dNk@clO5 z%rA8@8q2K~JEn8gEoOk8dINMuwbK0)jLu_t7eTJHfJxAc*E7+q;5uYHTszw;ZjHP;a<+*ZJrr)P3(3hukALY4NyU`r>2gpMvvF5CrTQ}} zIqSGTt|qL~wiaB<7EI}`CNMRVfZ6Md$X7N&Ln|&*a5yIz z#HDq$D>zX#ICIx6Hy$Zks%i$t6svQhGnt$-Y9+-v8kLOMDbHC|W_Hjbsz=Z93YE@a zi>WG^ucR)M=qJWT73_uN9Q?>oh)t(-UTL(_O=$^sAnjo)%J(sm52MXZ#HT z5z859rRAHxTzFx^R!1q$4^2pn$dfPqtQIr3T-peW0F&TjTxc=Qgkd8>0?!)1dNL-e$SRkLHya(7Rw z#Tc~R)bor9WKmU#o9&wkL3H5LRH=2#&1g>t1Cfh48nihG-AzqSBXL4i6Bn@-e6yo< zqQy_N(kjQ_I(~Ynw@zPQo*W);5e4rQ(p!t2Z9|*fUOT>Yc`BeoQd*S7@$x`9*OTIw zDfBTbrh`thy5vNk{8p)~bFqXnZ+}E9)mt&K0k!puo8x}x?xy?+Ey1hQLL1u5f(ReVfbQ$EMiRZlH zj=UN=R<=-M&1Yn=An-anRshp0J2% z_ZK003nXQHW8SnPyq<@E!>$GFhvd>3Aa>_)X-Ahg;hA%D>Nh>w1vO*7xMd8Q zg7hpJ*>krT5c`u0VtLpUc1-Iq?p0AI>!u3$y0ndVj?X%2a^q%agN`Y{Q0jR|j+jK(34|{7GZmUH^HK;(RL67Uz@q1^U93tC z;3%T=Qboaf)qq*qmldjyHLgITS<^-JOEV?wgZqSVT=CmFxF9DNTjcwLi<1jS+@DV_ ze|Y`olKgydetvLzd2)O~UZ4BR@~>ZzgVSHgk0+-`Jp#E!q2j}GM&H35ui(@m}n$^Mt678$WoM)2Z zsspaf7_YF-F5Z6l3_Cm_1;$E||0<2^#Y;`JQOY7kU&X0wCQ-9X9Ug(&80}e` zKDZ!bH)ILJhHXRuhnA*vT94uD+AbxaN)C`YM63$3u`FV-Hf+sOf;M1GOqbEb0d*QW zno&(65QGY|X0B)Pa;}y|qMD8_QnM&^Okv)z%nqifSN({=Xr|xiP{s2pJ&>1uZwGQ zv2f{fo3lcr8RsSnijmIRVmroM2_+LiebU2&IdVm_2uvq(69%=~Z;pHiX~tA3kLBuZ z;&3N?oY*K7+AZ5!?P$x_EVVF+la%$Zn5-@LKuCVzH`)_2u4G9tq^AeC>K|sbWQn&L zQrg^hSprxy)I`p>E~!|Fb0I{vT4p21R7w!I8PEh#d+oUKcy5i2szY;4fr_T3F@NK6 zqh~gjxEKaLK0VU&YF8Q@em^)nJ3c)+`NvQXAw~=GJek|{1wVC9e?wGm%C#gy$mN<9 zdNz%s9!+p&HD?J3ld^BTxnAYTPZ%VzB#=c3mqzK21&yviNwW36yw1VixnO6zxnm~O zs@CiCJn4`;KH}Mbl=%Xlj5^@|_Jp9fj&7=)@gj+}iC^Mjy#sIB_SR;#tjKw$=(}|JNrmF?@XZslhzQD zgCuc!MF4IJw!v=8HL>SJ)%mICXNZ!=x>>o7rl=+V$6^d3 z0|nBZux@q+f|(|RfShA&-Y;N~)>E(?Zf_e(HI8&N zWjq)~9&208ys=E`0VVzZ5@gz~Z&z=0{|secA;Ar09ra7vmJEw0k5C0tA(fbt*6hWg zL!o$z;Tv5*206vdxv+wVJL$@NAnb{Ajaa759I8rR3A28IszLysb{dRvZNj9?2}t?1 zwVZjONUFUHygJqzhaow^K`yOT!)O>r$TUX;hFL_DkEA(2n4uGcN3YmWwd6^mhaGNo z@4cf`O08iRV|6{PS6tY)NzE__E_peOs;(ML;yhO984OsGl&9!xiq>qDzzL-QRfw!w z3LHt$w(bariDvQewyeC6lMRx~IoXuiZnHAJFesY$ZNUA04A+p{0oPkBYE=<7>GvJ| z{@ecXKTaaZo6NT9!k2h$AdX$(K5d($aty^Q_#;x?^j#-B_Qh6Ow<`vtOS78@2h*~@ znLm8R&eNP{m}k?lOiWbnF00#jNGS55^@ zLFuW?`X&A(jD)4=Q34a?<*jx{JesdQj0$*7p(^1kc_h4p{^&DO8&t_j^H zV}yu=vx|n_4jfmeRF_H80NLEZ-@tD~{ZE^9*MKk=#x%hu_U&d6+ZW(#xSElwFXbir z<$Ubh5Lrylzdtx6?pn*7#}eDvI_D^=Z&1N(xdt<7?y%MET%gjl`qBHMI4*?BN_%z; z;+6yHU$A-TiF}PdkX zyLozKbaC+N?B#Lzs@w!87eKt6xxb8Y6c;1$#a=p6C?yf^PSS`t)tT8rvsG)Xy4+khc3xd|-a%9?U#1oUeV1QN!y+H^B8#={ z<%Kz_KkKb2I(2>W;F|6!It|_ATGHH{$;BsRM9VwWQI1FEPUSgGlTlq=Hcx!15wUu2 za~zbB%{E8Z&*!Pnf%W^6J-+kr{su;T4eu~wj>Wzmd^2jv!2-hl2XAW`8!F|$5vOfTmCLD75g$Zm| zo8syioJ?%$y>_xIlA`BXL5pbi9|~78ASS0g24XH#H@NH$Ua=A%9$(Zi%WqG7w4C}H z_v)`T1-4u0FmqNn(Uh=8BZ6_Pl~5^9X$p>_XZ{B>_|?K?3;88;M@cYyY14uk{mk9z zw9oN^ri7# z#BmMlV>Q3I;FY%+f>W3bqrA}Y56|9I7xS1;%gnj0XM;hywHkVAC%+HGOoJP>u`}4+ zt7gHjR1bf>A?a@B+0O2Y zj%+q4x9rSq#-+Qd+Q`U7c2?v&r3zS|{Ty8Miv4t{S-3Z2KugS8IB`vFq&Jn)F?3_||A(!4c`G zKFXDR-}^U-apk@cbHbH9Gt?bckLQ-Qjyj3UvZn$pH5sxXGTGs?y9$zR8 zux9T(zILCwVsBM4N6Qzg@fWUsAKHbrmn?%I_{FZ^R?Dp>lxR&HT*PxraS6-(<*l$> zWx$OnK1X3ti-|XPq#JZ_x!9S~9!1O| zedfh30~@>K6EgAxlB2M_V(9?hKGA@fPB%lU-}x<9$p{yY-ddXk!9jvoC@FRg$-GA> znbR~e+QV$MG^^n@9%7aaOT~tp%)Ai_9*?|(YDZ684p6z5@CFm&8;idtk!LYw?j#$7 z^e4o_&Cufq5GHp98POcvR`R3bWC~`Rn^aUN%uF4PMp)fh%tNvh1ns4_A*n5y1?F(> zAznY};?6^|R#-V8MA7Mx&?KMHfRJi{hvXo+p>t{a^56f~?~_xS0!rGIB>n#X1VLAB z(y&Y{xGF#D=C!}QEkPCecJS*fmNET#d1*!EmE2aGCvw{kS3k8iw*!;qQ~^MTUJq?3 zXWJ;WZ}qS3;31RqPx5r-e}+@8()>=Y{=;X*`S1IC`_20w_I3vk`JealJmh~qCN%$jPZaE?!$ouzr0jUrA<40Yj^#&3N_S-?Bc>6ovd**{Q q_&IRiuNEl(n+4On(e2^R%7^FSd3gR*&;Jhq0RR8!M4(6jG64V}@zg;8 literal 0 HcmV?d00001 diff --git a/packs/crossplane-1.16/charts/values.yaml b/packs/crossplane-1.16/charts/values.yaml new file mode 100644 index 00000000..6a319f21 --- /dev/null +++ b/packs/crossplane-1.16/charts/values.yaml @@ -0,0 +1,186 @@ +# helm-docs renders these comments into markdown. Use markdown formatting where +# appropiate. +# +# -- The number of Crossplane pod `replicas` to deploy. +replicas: 1 + +# -- The deployment strategy for the Crossplane and RBAC Manager pods. +deploymentStrategy: RollingUpdate + +image: + # -- Repository for the Crossplane pod image. + repository: xpkg.upbound.io/crossplane/crossplane + # -- The Crossplane image tag. Defaults to the value of `appVersion` in `Chart.yaml`. + tag: "" + # -- The image pull policy used for Crossplane and RBAC Manager pods. + pullPolicy: IfNotPresent + +# -- Add `nodeSelectors` to the Crossplane pod deployment. +nodeSelector: {} +# -- Add `tolerations` to the Crossplane pod deployment. +tolerations: [] +# -- Add `affinities` to the Crossplane pod deployment. +affinity: {} + +# -- Enable `hostNetwork` for the Crossplane deployment. Caution: enabling `hostNetwork` grants the Crossplane Pod access to the host network namespace. Consider setting `dnsPolicy` to `ClusterFirstWithHostNet`. +hostNetwork: false + +# -- Specify the `dnsPolicy` to be used by the Crossplane pod. +dnsPolicy: "" + +# -- Add custom `labels` to the Crossplane pod deployment. +customLabels: {} + +# -- Add custom `annotations` to the Crossplane pod deployment. +customAnnotations: {} + +serviceAccount: + # -- Add custom `annotations` to the Crossplane ServiceAccount. + customAnnotations: {} + +# -- Enable [leader election](https://docs.crossplane.io/latest/concepts/pods/#leader-election) for the Crossplane pod. +leaderElection: true +# -- Add custom arguments to the Crossplane pod. +args: [] + +provider: + # -- A list of Provider packages to install. + packages: [] + +configuration: + # -- A list of Configuration packages to install. + packages: [] + +function: + # -- A list of Function packages to install + packages: [] + +# -- The imagePullSecret names to add to the Crossplane ServiceAccount. +imagePullSecrets: [] + +registryCaBundleConfig: + # -- The ConfigMap name containing a custom CA bundle to enable fetching packages from registries with unknown or untrusted certificates. + name: "" + # -- The ConfigMap key containing a custom CA bundle to enable fetching packages from registries with unknown or untrusted certificates. + key: "" + +service: + # -- Configure annotations on the service object. Only enabled when webhooks.enabled = true + customAnnotations: {} + +webhooks: + # -- Enable webhooks for Crossplane and installed Provider packages. + enabled: true + +rbacManager: + # -- Deploy the RBAC Manager pod and its required roles. + deploy: true + # -- Don't install aggregated Crossplane ClusterRoles. + skipAggregatedClusterRoles: false + # -- The number of RBAC Manager pod `replicas` to deploy. + replicas: 1 + # -- Enable [leader election](https://docs.crossplane.io/latest/concepts/pods/#leader-election) for the RBAC Manager pod. + leaderElection: true + # -- Add custom arguments to the RBAC Manager pod. + args: [] + # -- Add `nodeSelectors` to the RBAC Manager pod deployment. + nodeSelector: {} + # -- Add `tolerations` to the RBAC Manager pod deployment. + tolerations: [] + # -- Add `affinities` to the RBAC Manager pod deployment. + affinity: {} + +# -- The PriorityClass name to apply to the Crossplane and RBAC Manager pods. +priorityClassName: "" + +resourcesCrossplane: + limits: + # -- CPU resource limits for the Crossplane pod. + cpu: 500m + # -- Memory resource limits for the Crossplane pod. + memory: 1024Mi + requests: + # -- CPU resource requests for the Crossplane pod. + cpu: 100m + # -- Memory resource requests for the Crossplane pod. + memory: 256Mi + +securityContextCrossplane: + # -- The user ID used by the Crossplane pod. + runAsUser: 65532 + # -- The group ID used by the Crossplane pod. + runAsGroup: 65532 + # -- Enable `allowPrivilegeEscalation` for the Crossplane pod. + allowPrivilegeEscalation: false + # -- Set the Crossplane pod root file system as read-only. + readOnlyRootFilesystem: true + +packageCache: + # -- Set to `Memory` to hold the package cache in a RAM backed file system. Useful for Crossplane development. + medium: "" + # -- The size limit for the package cache. If medium is `Memory` the `sizeLimit` can't exceed Node memory. + sizeLimit: 20Mi + # -- The name of a PersistentVolumeClaim to use as the package cache. Disables the default package cache `emptyDir` Volume. + pvc: "" + # -- The name of a ConfigMap to use as the package cache. Disables the default package cache `emptyDir` Volume. + configMap: "" + +resourcesRBACManager: + limits: + # -- CPU resource limits for the RBAC Manager pod. + cpu: 100m + # -- Memory resource limits for the RBAC Manager pod. + memory: 512Mi + requests: + # -- CPU resource requests for the RBAC Manager pod. + cpu: 100m + # -- Memory resource requests for the RBAC Manager pod. + memory: 256Mi + +securityContextRBACManager: + # -- The user ID used by the RBAC Manager pod. + runAsUser: 65532 + # -- The group ID used by the RBAC Manager pod. + runAsGroup: 65532 + # -- Enable `allowPrivilegeEscalation` for the RBAC Manager pod. + allowPrivilegeEscalation: false + # -- Set the RBAC Manager pod root file system as read-only. + readOnlyRootFilesystem: true + +metrics: + # -- Enable Prometheus path, port and scrape annotations and expose port 8080 for both the Crossplane and RBAC Manager pods. + enabled: false + +# -- Add custom environmental variables to the Crossplane pod deployment. +# Replaces any `.` in a variable name with `_`. For example, `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`. +extraEnvVarsCrossplane: {} + +# -- Add custom environmental variables to the RBAC Manager pod deployment. +# Replaces any `.` in a variable name with `_`. For example, `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`. +extraEnvVarsRBACManager: {} + +# -- Add a custom `securityContext` to the Crossplane pod. +podSecurityContextCrossplane: {} + +# -- Add a custom `securityContext` to the RBAC Manager pod. +podSecurityContextRBACManager: {} + +# -- Add custom `volumes` to the Crossplane pod. +extraVolumesCrossplane: {} + +# -- Add custom `volumeMounts` to the Crossplane pod. +extraVolumeMountsCrossplane: {} + +# -- To add arbitrary Kubernetes Objects during a Helm Install +extraObjects: [] + # - apiVersion: pkg.crossplane.io/v1alpha1 + # kind: ControllerConfig + # metadata: + # name: aws-config + # annotations: + # eks.amazonaws.com/role-arn: arn:aws:iam::123456789101:role/example + # helm.sh/hook: post-install + # spec: + # podSecurityContext: + # fsGroup: 2000 + diff --git a/packs/crossplane-1.16/logo.png b/packs/crossplane-1.16/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..94280b87bc667f8700a8c06d52561f7354f3b6a8 GIT binary patch literal 91169 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 A!T Date: Fri, 24 May 2024 14:48:18 -0400 Subject: [PATCH 02/22] Updated deprecated status --- packs/crossplane-1.7.0/pack.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packs/crossplane-1.7.0/pack.json b/packs/crossplane-1.7.0/pack.json index fb70f712..bf882931 100644 --- a/packs/crossplane-1.7.0/pack.json +++ b/packs/crossplane-1.7.0/pack.json @@ -14,6 +14,6 @@ "layer":"addon", "name": "crossplane", "version": "1.7.0", - "eol": "2024-06-30" + "system_state": "deprecated" } \ No newline at end of file From ff6bb69f68b1daa7881341f69afbb28ca843672a Mon Sep 17 00:00:00 2001 From: Justin Barksdale Date: Fri, 24 May 2024 14:48:51 -0400 Subject: [PATCH 03/22] Updated deprecated status --- packs/crossplane-1.7.0/pack.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packs/crossplane-1.7.0/pack.json b/packs/crossplane-1.7.0/pack.json index bf882931..6aa66427 100644 --- a/packs/crossplane-1.7.0/pack.json +++ b/packs/crossplane-1.7.0/pack.json @@ -2,7 +2,8 @@ "addonType": "system app", "annotations": { "source": "community", - "contributor" : "spectrocloud" + "contributor" : "spectrocloud", + "system_state": "deprecated" }, "cloudTypes": [ "all" @@ -13,7 +14,6 @@ ], "layer":"addon", "name": "crossplane", - "version": "1.7.0", - "system_state": "deprecated" + "version": "1.7.0" } \ No newline at end of file From 8cbc146a832b73ea7dd0c9f44e683e87ae2ff2eb Mon Sep 17 00:00:00 2001 From: Justin Barksdale Date: Fri, 24 May 2024 15:27:03 -0400 Subject: [PATCH 04/22] updated namespace --- packs/crossplane-1.16/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packs/crossplane-1.16/values.yaml b/packs/crossplane-1.16/values.yaml index a02bd489..2f34c284 100644 --- a/packs/crossplane-1.16/values.yaml +++ b/packs/crossplane-1.16/values.yaml @@ -1,7 +1,7 @@ pack: #The namespace (on the target cluster) to install this chart #When not found, a new namespace will be created - namespace: "crossplane" + namespace: "crossplane-system" charts: crossplane: From 9e9eddc09dbb764a199a29931e695b92a7fed8e4 Mon Sep 17 00:00:00 2001 From: Justin Barksdale Date: Tue, 28 May 2024 06:21:33 -0400 Subject: [PATCH 05/22] Removed Constraints --- packs/crossplane-1.16/pack.json | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packs/crossplane-1.16/pack.json b/packs/crossplane-1.16/pack.json index 7f7a563d..852c0830 100644 --- a/packs/crossplane-1.16/pack.json +++ b/packs/crossplane-1.16/pack.json @@ -13,16 +13,6 @@ ], "layer":"addon", "name": "crossplane", - "version": "1.16.0", - "constraints": { - "dependencies": [ - { - "packName": "kubernetes", - "layer": "k8s", - "minVersion": "1.27.0", - "type": "required" - } - ] - } + "version": "1.16.0" } \ No newline at end of file From 117c2b7cc31d708e32fcdaaf9e1b45f863b8b83b Mon Sep 17 00:00:00 2001 From: Justin Barksdale Date: Tue, 28 May 2024 06:37:29 -0400 Subject: [PATCH 06/22] removed deprecated gloud providers --- packs/crossplane-1.16/presets.yaml | 44 +----------------------------- 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/packs/crossplane-1.16/presets.yaml b/packs/crossplane-1.16/presets.yaml index 1ae4a5b6..35186399 100644 --- a/packs/crossplane-1.16/presets.yaml +++ b/packs/crossplane-1.16/presets.yaml @@ -8,46 +8,4 @@ presets: crossplane: provider: packages: - - "xpkg.upbound.io/crossplane-contrib/provider-palette:v0.19.2" - - name: "aws-provider" - displayName: "Enable AWS Provider" - group: "Provider" - remove: [] - add: | - charts: - crossplane: - provider: - packages: - - "xpkg.upbound.io/upbound/provider-aws:v1.5.0" - - name: "azure-provider" - displayName: "Enable Azure Provider" - group: "Provider" - remove: [] - add: | - charts: - crossplane: - provider: - packages: - - "xpkg.upbound.io/crossplane-contrib/provider-azure:v0.20.1" - - name: "gcp-provider" - displayName: "Enable GCP Provider" - group: "Provider" - remove: [] - add: | - charts: - crossplane: - provider: - packages: - - "xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0" - - name: "aws-gcp-azure-provider" - displayName: "Enable AWS, GCP, Azure Provider" - group: "Provider" - remove: [] - add: | - charts: - crossplane: - provider: - packages: - - "xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0" - - "xpkg.upbound.io/crossplane-contrib/provider-azure:v0.20.1" - - "xpkg.upbound.io/upbound/provider-aws:v1.5.0" \ No newline at end of file + - "xpkg.upbound.io/crossplane-contrib/provider-palette:v0.19.2" \ No newline at end of file From 4fea9bd7657895ea1e6b79a5c0c6a6bb02123f04 Mon Sep 17 00:00:00 2001 From: Justin Barksdale Date: Tue, 28 May 2024 06:38:38 -0400 Subject: [PATCH 07/22] updated README --- packs/crossplane-1.16/{README-template.md => README.md} | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) rename packs/crossplane-1.16/{README-template.md => README.md} (89%) diff --git a/packs/crossplane-1.16/README-template.md b/packs/crossplane-1.16/README.md similarity index 89% rename from packs/crossplane-1.16/README-template.md rename to packs/crossplane-1.16/README.md index 56ba8119..83370a54 100644 --- a/packs/crossplane-1.16/README-template.md +++ b/packs/crossplane-1.16/README.md @@ -15,7 +15,7 @@ Kuberernetes >= 1.27.0 Installing a provider creates new Kubernetes resources representing the Provider’s APIs. Installing a provider also creates a Provider pod that’s responsible for reconciling the Provider’s APIs into the Kubernetes cluster. Providers constantly watch the state of the desired managed resources and create any external resources that are missing. -Install a Provider with a Crossplane Provider object setting the spec.package value to the location of the provider package. +Install a Provider with a Crossplane Provider object setting the spec.package value to the location of the provider package. Additional providers can be found in the [Upboud Marketplace](https://marketplace.upbound.io/) *For Example* Install the [Palette Provider](https://marketplace.upbound.io/providers/crossplane-contrib/provider-palette/v0.19.2) @@ -31,4 +31,5 @@ spec: ## References Crossplane Provider Guide - https://docs.crossplane.io/latest/concepts/providers/ -Crossplane Concepts - https://docs.crossplane.io/latest/concepts/ \ No newline at end of file +Crossplane Concepts - https://docs.crossplane.io/latest/concepts/ +Upbound Marketplace - https://marketplace.upbound.io/ \ No newline at end of file From 6561ab199ab28149c3d337b27b4561ddeb51db1d Mon Sep 17 00:00:00 2001 From: Adelina Simion <43963729+addetz@users.noreply.github.com> Date: Mon, 6 May 2024 13:07:48 +0200 Subject: [PATCH 08/22] Add new pack version - Hello Universe - 1.1.2 DOC-1158 (#70) * add hello-universe 1.1.2 pack DOC-1158 This patch adds a new version of the hello-universe pack. It has 2 presets and bumps the image version. * adjust hello-universe schema DOC-1158 * consolidate to one single manifest DOC-1158 * rename values with camel case * add images for API and DB DOC-1158 * Update packs/hello-universe-1.1.2/README.md Co-authored-by: Karl Cardenas --------- Co-authored-by: Karl Cardenas --- packs/hello-universe-1.1.2/README.md | 59 ++++ packs/hello-universe-1.1.2/logo.png | Bin 0 -> 88384 bytes .../manifests/hello-universe.yaml | 309 ++++++++++++++++++ packs/hello-universe-1.1.2/pack.json | 15 + packs/hello-universe-1.1.2/presets.yaml | 32 ++ packs/hello-universe-1.1.2/schema.yaml | 44 +++ packs/hello-universe-1.1.2/values.yaml | 16 + 7 files changed, 475 insertions(+) create mode 100644 packs/hello-universe-1.1.2/README.md create mode 100644 packs/hello-universe-1.1.2/logo.png create mode 100644 packs/hello-universe-1.1.2/manifests/hello-universe.yaml create mode 100644 packs/hello-universe-1.1.2/pack.json create mode 100644 packs/hello-universe-1.1.2/presets.yaml create mode 100644 packs/hello-universe-1.1.2/schema.yaml create mode 100644 packs/hello-universe-1.1.2/values.yaml diff --git a/packs/hello-universe-1.1.2/README.md b/packs/hello-universe-1.1.2/README.md new file mode 100644 index 00000000..0d0c548e --- /dev/null +++ b/packs/hello-universe-1.1.2/README.md @@ -0,0 +1,59 @@ +# Hello Universe + +[Hello Universe](https://github.com/spectrocloud/hello-universe) is a demo web application utilized to help users learn more about [Palette](https://docs.spectrocloud.com/introduction) and its features. + +You can deploy it using two preset configurations: +- A standalone front-end application. It provides a click counter that is saved locally and displays Spectro Cloud themed images. +- A three-tier application with a front-end application, API server and PostgreSQL database into a Kubernetes cluster. It provides a click counter that is saved in the deployed database and displays Spectro Cloud themed images. You can read more about this configuration on the Hello Universe [README](https://github.com/spectrocloud/hello-universe?tab=readme-ov-file#reverse-proxy-with-kubernetes). + +## Prerequisites + +- A Palette account. + +- A cluster profile where the Hello Universe pack can be integrated. + +- A Palette cluster with port `:8080` available. If port 8080 is not available, you can set a different port in the **values.yaml** file. + +- If you are using the **Enable Hello Universe API** preset, you will need the `:3000` port available on your cluster too. Check out the [Usage](#usage) section for further details. + +- Ensure sufficient CPU resources within the cluster to allocate a minimum of 500 milliCPU and a maximum of 500 milliCPU per replica. + +## Parameters + +The following parameters are applied to the **hello-universe.yaml** manifest through the **values.yaml** file. Users do not need to take any additional actions regarding these parameters. + +| **Parameter** | **Description** | **Default Value** | **Required** | +| --------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------- | ------------ | +| `manifests.namespace` | The namespace in which the application will be deployed. | `hello-universe` | Yes | +| `manifests.images.hellouniverse` | The [`hello-universe`](https://github.com/spectrocloud/hello-universe) application image that will be utilized to create the containers. | `ghcr.io/spectrocloud/hello-universe:1.1.2`/ `ghcr.io/spectrocloud/hello-universe:1.1.2-proxy` | Yes | +| `manifests.images.hellouniverseapi` | The [`hello-universe-api`](https://github.com/spectrocloud/hello-universe-api) application image that will be utilized to create the containers. | `ghcr.io/spectrocloud/hello-universe-api:1.0.12` | No | +| `manifests.images.hellouniversedb` | The [`hello-universe-db`](https://github.com/spectrocloud/hello-universe-db) application image that will be utilized to create the containers. | `ghcr.io/spectrocloud/hello-universe-db:1.0.2` | No | +| `manifests.apiEnabled` | The flag that indicates whether to deploy the UI application as standalone or together with the API server. | `false` | Yes | +| `manifests.port` | The cluster port number on which the service will listen for incoming traffic. | `8080` | Yes | +| `manifests.replicas` | The number of Pods to be created. | `1` | Yes | +| `manifests.dbPassword` | The base64 encoded database password to connect to the API database. | `REPLACE_ME` | No | +| `manifests.authToken` | The base64 encoded auth token for the API connection. | `REPLACE_ME` | No | + +## Usage + +The Hello Universe pack has two presets that you can select: +- **Disable Hello Universe API** configures Hello Universe as a standalone frontend application. This is the default configuration of the pack. +- **Enable Hello Universe API** configures Hello Universe as a three-tier application with a frontend, API server, and Postgres database. + +To utilize the Hello Universe pack, create either a [full Palette cluster profile](https://docs.spectrocloud.com/profiles/cluster-profiles/create-cluster-profiles/create-full-profile) or an [add-on Palette cluster profile](https://docs.spectrocloud.com/profiles/cluster-profiles/create-cluster-profiles/create-addon-profile/) and add the pack to your profile. You can select the preset you wish to deploy on the cluster profile creation page. + +If your infrastructure provider does not offer a native load balancer solution, such as VMware and MAAS, the [MetalLB](https://docs.spectrocloud.com/integrations/metallb) pack must be included to the cluster profile to help the LoadBalancer service specified in the manifest obtain an IP address. + +After defining the cluster profile, use it to deploy a new cluster or attach it as an add-on profile to an existing cluster. + +Once the cluster status displays **Running** and **Healthy**, access the Hello Universe application through the exposed service URL along with the displayed port number. + +## References + +- [Hello Universe GitHub Repository](https://github.com/spectrocloud/hello-universe) + +- [Hello Universe API GitHub Repository](https://github.com/spectrocloud/hello-universe-api) + +- [Deploy a Custom Pack Tutorial](https://docs.spectrocloud.com/registries-and-packs/deploy-pack/) + +- [Registries and Packs](https://docs.spectrocloud.com/registries-and-packs/) diff --git a/packs/hello-universe-1.1.2/logo.png b/packs/hello-universe-1.1.2/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..eeae3434e51b554c16914826c5d992b4f4dd90a7 GIT binary patch literal 88384 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 EKb9;gUjP6A literal 0 HcmV?d00001 diff --git a/packs/hello-universe-1.1.2/manifests/hello-universe.yaml b/packs/hello-universe-1.1.2/manifests/hello-universe.yaml new file mode 100644 index 00000000..5b233d67 --- /dev/null +++ b/packs/hello-universe-1.1.2/manifests/hello-universe.yaml @@ -0,0 +1,309 @@ +{{ if not .Values.apiEnabled }} + +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.namespace }} +--- +apiVersion: v1 +kind: Service +metadata: + name: hello-universe-service + namespace: {{ .Values.namespace }} +spec: + type: LoadBalancer + selector: + app: hello-universe + ports: + - protocol: TCP + port: {{ .Values.port }} + targetPort: 8080 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: hello-universe-deployment + namespace: {{ .Values.namespace }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app: hello-universe + template: + metadata: + labels: + app: hello-universe + spec: + containers: + - name: hello-universe + image: {{ .Values.images.hellouniverse }} + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + resources: + requests: + cpu: "100m" # requesting 100 milliCPU + memory: "512Mi" # requesting 512 MiB of memory + limits: + cpu: "200m" # limiting to 200 milliCPU + memory: "1024Mi" # requesting 1024 MiB of memory + +{{ end }} + +{{ if .Values.apiEnabled }} + +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Values.namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: service-reader +rules: + - apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "watch"] +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: hello-universe-role + namespace: {{ .Values.namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: service-reader-binding +subjects: + - kind: ServiceAccount + name: hello-universe-role + namespace: {{ .Values.namespace }} +roleRef: + kind: ClusterRole + name: service-reader + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: v1 +kind: Service +metadata: + name: ui + namespace: {{ .Values.namespace }} +spec: + selector: + app: ui + ports: + - protocol: TCP + name: ui + port: {{ .Values.port }} + targetPort: 8080 + - protocol: TCP + name: api + port: 3000 + targetPort: 3000 + type: LoadBalancer +--- +apiVersion: v1 +kind: Secret +metadata: + name: db-password + namespace: {{ .Values.namespace }} +type: Opaque +data: + db-password: {{ .Values.dbPassword }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: auth-token + namespace: {{ .Values.namespace }} +type: Opaque +data: + auth-token: {{ .Values.authToken }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres + namespace: {{ .Values.namespace }} +spec: + selector: + matchLabels: + app: postgres + replicas: 1 + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: {{ .Values.images.hellouniversedb }} + ports: + - containerPort: 5432 + name: postgres + resources: + limits: + memory: "500Mi" + cpu: "500m" + requests: + memory: "500Mi" + cpu: "500m" +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: {{ .Values.namespace }} +spec: + selector: + app: postgres + ports: + - protocol: TCP + port: 5432 + targetPort: 5432 + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api + namespace: {{ .Values.namespace }} +spec: + selector: + matchLabels: + app: api + replicas: 1 + template: + metadata: + labels: + app: api + spec: + serviceAccountName: hello-universe-role + containers: + - name: api + image: {{ .Values.images.hellouniverseapi }} + ports: + - containerPort: 3000 + name: api + env: + - name: db-password + valueFrom: + secretKeyRef: + name: db-password + key: db-password + - name: DB_HOST + value: "postgres.{{ .Values.namespace }}.svc.cluster.local" + - name: PORT + value: "3000" + - name: DB_USER + value: "postgres" + - name: DB_NAME + value: "counter" + - name: DB_ENCRYPTION + value: "disable" + - name: DB_INIT + value: "false" + - name: AUTHORIZATION + value: "true" + resources: + limits: + memory: "500Mi" + cpu: "500m" + requests: + memory: "500Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /api/v1/health + port: 3000 + initialDelaySeconds: 35 + periodSeconds: 3 + readinessProbe: + httpGet: + path: /api/v1/health + port: 3000 + initialDelaySeconds: 30 + periodSeconds: 3 +--- +apiVersion: v1 +kind: Service +metadata: + name: api + namespace: {{ .Values.namespace }} +spec: + selector: + app: api + ports: + - protocol: TCP + port: 3000 + targetPort: 3000 + type: ClusterIP # If you want to expose the API service, change this value to LoadBalancer. See below for an example. + # type: Loadbalancer +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ui + namespace: {{ .Values.namespace }} +spec: + selector: + matchLabels: + app: ui + replicas: {{ .Values.replicas }} + template: + metadata: + labels: + app: ui + spec: + serviceAccountName: hello-universe-role + initContainers: + - name: init-container + image: busybox + command: + ["/bin/sh", "-c", "echo 'sleeping for 30 seconds' && sleep 30"] + containers: + - name: ui + image: {{ .Values.images.hellouniverse }} + imagePullPolicy: Always + ports: + - containerPort: 8080 + name: ui + env: + - name: TOKEN + valueFrom: + secretKeyRef: + name: auth-token + key: auth-token + - name: API_URI + # Leave empty and set QUERY_K8S_API to true to leverage a single loadbalancer. + # Otherwise, set to the API service's URL and set QUERY_K8S_API to false + value: "" + - name: SVC_URI + value: "api.{{ .Values.namespace }}.svc.cluster.local:3000" + - name: API_VERSION + value: "1" + - name: QUERY_K8S_API + value: "true" + resources: + limits: + memory: "500Mi" + cpu: "500m" + requests: + memory: "500Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 40 + periodSeconds: 3 + readinessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 35 + periodSeconds: 3 + +{{ end }} diff --git a/packs/hello-universe-1.1.2/pack.json b/packs/hello-universe-1.1.2/pack.json new file mode 100644 index 00000000..f80e99f7 --- /dev/null +++ b/packs/hello-universe-1.1.2/pack.json @@ -0,0 +1,15 @@ +{ + "addonType": "app services", + "annotations": { + "source": "community", + "contributor": "spectrocloud" + }, + "cloudTypes": ["all"], + "displayName": "Hello Universe", + "kubeManifests": [ + "manifests/hello-universe.yaml" + ], + "layer": "addon", + "name": "hello-universe", + "version": "1.1.2" +} diff --git a/packs/hello-universe-1.1.2/presets.yaml b/packs/hello-universe-1.1.2/presets.yaml new file mode 100644 index 00000000..77cdb6c1 --- /dev/null +++ b/packs/hello-universe-1.1.2/presets.yaml @@ -0,0 +1,32 @@ +presets: + - name: "disable-api" + displayName: "Disable Hello Universe API" + group: "Backend" + remove: [] + add: | + manifests: + hello-universe: + images: + hellouniverse: ghcr.io/spectrocloud/hello-universe:1.1.2 + apiEnabled: false + namespace: hello-universe + port: 8080 + replicas: 1 + + - name: "enable-api" + displayName: "Enable Hello Universe API" + group: "Backend" + remove: [] + add: | + manifests: + hello-universe: + images: + hellouniverse: ghcr.io/spectrocloud/hello-universe:1.1.2-proxy + hellouniverseapi: ghcr.io/spectrocloud/hello-universe-api:1.0.12 + hellouniversedb: ghcr.io/spectrocloud/hello-universe-db:1.0.2 + apiEnabled: true + namespace: hello-universe + port: 8080 + replicas: 1 + dbPassword: REPLACE_ME # Add base64 encoded password + authToken: REPLACE_ME # Add base64 encoded token diff --git a/packs/hello-universe-1.1.2/schema.yaml b/packs/hello-universe-1.1.2/schema.yaml new file mode 100644 index 00000000..d7f2ee55 --- /dev/null +++ b/packs/hello-universe-1.1.2/schema.yaml @@ -0,0 +1,44 @@ +manifests.hello-universe.namespace: + # The namespace in which the UI application will be deployed. + # The namespace should be specified as a string. + schema: '{{ required | format "${string}" | hints "Enter the namespace in which the application will be deployed."}}' + +manifests.hello-universe.images.hellouniverse: + # The application image. + # Ensure that the image follows the required format: registry/repository:version. + schema: '{{ required | format "${string}" | hints "Enter the UI application image. Ensure that it follows the required format: registry/repository:version." }}' + +manifests.hello-universe.images.hellouniverseapi: + # The hello-universe-api application image. + # Ensure that the image follows the required format: registry/repository:version. + schema: '{{ format "${string}" | hints "Enter the API application image. Ensure that it follows the required format: registry/repository:version." }}' + +manifests.hello-universe.images.hellouniversedb: + # The hello-universe-db application image. + # Ensure that the image follows the required format: registry/repository:version. + schema: '{{ format "${string}" | hints "Enter the API application image. Ensure that it follows the required format: registry/repository:version." }}' + +manifests.hello-universe.port: + # The cluster port number on which the UI service will listen for incoming traffic. + # The port should be specified as a number. + schema: '{{ required | format "${number}" | hints "Enter the cluster port number on which the UI service will listen for incoming traffic."}}' + +manifests.hello-universe.replicas: + # The number of replicas of the UI application to be created. + # The replicas should be specified as a number. + schema: '{{ required | format "${number}" | hints "Enter the number of replicas of the UI application."}}' + +manifests.hello-universe.dbPassword: + # The database password to connect the hello-universe-api to the hello-universe-db. + # The password should be specified as a base64 encoded string. + schema: '{{ format "${string}" | hints "Enter the base64 encoded database password to connect to."}}' + +manifests.hello-universe.authToken: + # The auth token to connect the hello-universe-api to the hello-universe-db. + # The token should be specified as a base64 encoded string. + schema: '{{ format "${string}" | hints "Enter the base64 encoded auth token to connect to the API with."}}' + +manifests.hello-universe.apiEnabled: + # Flag to indicate whether Hello Universe should be deployed with API server or not. + # The flag should be specified with true or false. + schema: '{{ required | format "${boolean}" | hints "Enter the base64 encoded auth token to connect to the API with."}}' diff --git a/packs/hello-universe-1.1.2/values.yaml b/packs/hello-universe-1.1.2/values.yaml new file mode 100644 index 00000000..cad82ca6 --- /dev/null +++ b/packs/hello-universe-1.1.2/values.yaml @@ -0,0 +1,16 @@ +# spectrocloud.com/enabled-presets: Backend:disable-api + +pack: + content: + images: + - image: ghcr.io/spectrocloud/hello-universe:1.1.2 + + +manifests: + hello-universe: + images: + hellouniverse: ghcr.io/spectrocloud/hello-universe:1.1.2 + apiEnabled: false + namespace: hello-universe + port: 8080 + replicas: 1 From 55334cc41bb67b205d6c653736ba813b971181ac Mon Sep 17 00:00:00 2001 From: Tyler Gillson Date: Tue, 7 May 2024 22:55:50 -0600 Subject: [PATCH 09/22] feat: add k8gb pack Signed-off-by: Tyler Gillson --- packs/k8gb-0.12.2/README.md | 10 + packs/k8gb-0.12.2/charts/k8gb-0.12.2.tgz | Bin 0 -> 31534 bytes packs/k8gb-0.12.2/charts/k8gb/.helmignore | 23 + packs/k8gb-0.12.2/charts/k8gb/Chart.lock | 6 + packs/k8gb-0.12.2/charts/k8gb/Chart.yaml | 71 ++ packs/k8gb-0.12.2/charts/k8gb/README.md | 128 ++++ .../charts/k8gb/_helm-docs-template.gotmpl | 36 + .../charts/k8gb/charts/coredns-1.15.3.tgz | Bin 0 -> 12345 bytes .../k8gb/crd/dns-endpoint-crd-manifest.yaml | 93 +++ .../charts/k8gb/crd/k8gb.absa.oss_gslbs.yaml | 374 ++++++++++ .../charts/k8gb/templates/NOTES.txt | 25 + .../charts/k8gb/templates/_helpers.tpl | 154 ++++ .../charts/k8gb/templates/coredns-cm.yaml | 25 + .../charts/k8gb/templates/coredns/rbac.yaml | 35 + .../charts/k8gb/templates/crds-template.yaml | 9 + .../charts/k8gb/templates/deployment.yaml | 147 ++++ .../templates/external-dns/external-dns.yaml | 74 ++ .../k8gb/templates/external-dns/rbac.yaml | 37 + .../charts/k8gb/templates/infoblox-cm.yaml | 14 + .../k8gb/templates/metrics-service.yaml | 16 + .../templates/otel/jaeger-deployment.yaml | 39 ++ .../k8gb/templates/otel/jaeger-svc.yaml | 27 + .../k8gb/templates/otel/otel-config.yaml | 36 + .../charts/k8gb/templates/otel/otel-svc.yaml | 21 + .../charts/k8gb/templates/role.yaml | 59 ++ .../charts/k8gb/templates/role_binding.yaml | 16 + .../k8gb/templates/service_account.yaml | 10 + .../charts/k8gb/templates/servicemonitor.yaml | 14 + .../charts/k8gb/values.schema.json | 663 ++++++++++++++++++ packs/k8gb-0.12.2/charts/k8gb/values.yaml | 197 ++++++ packs/k8gb-0.12.2/logo.png | Bin 0 -> 2681 bytes packs/k8gb-0.12.2/pack.json | 17 + packs/k8gb-0.12.2/schema.yaml | 2 + packs/k8gb-0.12.2/values.yaml | 211 ++++++ 34 files changed, 2589 insertions(+) create mode 100644 packs/k8gb-0.12.2/README.md create mode 100644 packs/k8gb-0.12.2/charts/k8gb-0.12.2.tgz create mode 100644 packs/k8gb-0.12.2/charts/k8gb/.helmignore create mode 100644 packs/k8gb-0.12.2/charts/k8gb/Chart.lock create mode 100644 packs/k8gb-0.12.2/charts/k8gb/Chart.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/README.md create mode 100644 packs/k8gb-0.12.2/charts/k8gb/_helm-docs-template.gotmpl create mode 100644 packs/k8gb-0.12.2/charts/k8gb/charts/coredns-1.15.3.tgz create mode 100644 packs/k8gb-0.12.2/charts/k8gb/crd/dns-endpoint-crd-manifest.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/crd/k8gb.absa.oss_gslbs.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/NOTES.txt create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/_helpers.tpl create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/coredns-cm.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/coredns/rbac.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/crds-template.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/deployment.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/external-dns/external-dns.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/external-dns/rbac.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/infoblox-cm.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/metrics-service.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/otel/jaeger-deployment.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/otel/jaeger-svc.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/otel/otel-config.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/otel/otel-svc.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/role.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/role_binding.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/service_account.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/templates/servicemonitor.yaml create mode 100644 packs/k8gb-0.12.2/charts/k8gb/values.schema.json create mode 100644 packs/k8gb-0.12.2/charts/k8gb/values.yaml create mode 100644 packs/k8gb-0.12.2/logo.png create mode 100644 packs/k8gb-0.12.2/pack.json create mode 100644 packs/k8gb-0.12.2/schema.yaml create mode 100644 packs/k8gb-0.12.2/values.yaml diff --git a/packs/k8gb-0.12.2/README.md b/packs/k8gb-0.12.2/README.md new file mode 100644 index 00000000..b11870df --- /dev/null +++ b/packs/k8gb-0.12.2/README.md @@ -0,0 +1,10 @@ +# K8GB - Kubernetes Global Balancer + +## Overview +The k8gb pack installs the Kubernetes Global Balancer. + +## CloudTypes supported: +Supported for all cloudTypes. + +## References: +* [k8gb](https://github.com/k8gb-io/k8gb) diff --git a/packs/k8gb-0.12.2/charts/k8gb-0.12.2.tgz b/packs/k8gb-0.12.2/charts/k8gb-0.12.2.tgz new file mode 100644 index 0000000000000000000000000000000000000000..05d9fa420b254771e91fb8df319995cce4d459b2 GIT binary patch literal 31534 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 literal 0 HcmV?d00001 diff --git a/packs/k8gb-0.12.2/charts/k8gb/.helmignore b/packs/k8gb-0.12.2/charts/k8gb/.helmignore new file mode 100644 index 00000000..5d9272cd --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + diff --git a/packs/k8gb-0.12.2/charts/k8gb/Chart.lock b/packs/k8gb-0.12.2/charts/k8gb/Chart.lock new file mode 100644 index 00000000..7fd7b384 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: coredns + repository: https://absaoss.github.io/coredns-helm + version: 1.15.3 +digest: sha256:1d0d37c5c794791fd23077b7eec889ed814b5acca9c45084c23889838c7535b3 +generated: "2021-09-22T16:22:52.020645+02:00" diff --git a/packs/k8gb-0.12.2/charts/k8gb/Chart.yaml b/packs/k8gb-0.12.2/charts/k8gb/Chart.yaml new file mode 100644 index 00000000..3b6a20a9 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/Chart.yaml @@ -0,0 +1,71 @@ +apiVersion: v2 +name: k8gb +description: A Helm chart for Kubernetes Global Balancer +icon: https://www.k8gb.io/assets/images/icon-192x192.png +type: application +version: v0.12.2 +appVersion: v0.12.2 +kubeVersion: ">= 1.19.0-0" + +dependencies: + - name: coredns + repository: https://absaoss.github.io/coredns-helm + version: 1.15.3 + +home: https://www.k8gb.io/ +sources: + - https://github.com/k8gb-io/k8gb + +keywords: + - gslb + - dns-lb + - kuberneters-global-balancer + - kubernetes-operator + - balancer + - multi-cluster + +maintainers: + - email: dinar.valeev@absa.africa + name: Dinar Valeev + - email: jiri.kremser@gmail.com + name: Jiri Kremser + - email: kuritka@gmail.com + name: Michal Kuritka + - email: yury.tsarev@absa.africa + name: Yury Tsarev + +annotations: + artifacthub.io/operator: "true" + artifacthub.io/operatorCapabilities: Seamless Upgrades + artifacthub.io/crds: | + - kind: Gslb + version: v1beta1 + name: gslbs.k8gb.absa.oss + displayName: Gslb + description: Gslb resource for global load balancing strategy configuration + - kind: DNSEndpoint + name: dnsendpoints.externaldns.k8s.io + version: v1alpha1 + displayName: DNSEndpoint + description: Using ExternalDNS it synchronizes exposed Kubernetes Services and Ingresses with DNS providers + artifacthub.io/crdsExamples: | + - apiVersion: k8gb.absa.oss/v1beta1 + kind: Gslb + metadata: + name: test-gslb-failover + namespace: test-gslb + spec: + ingress: + rules: + - host: failover.test.k8gb.io # Desired GSLB enabled FQDN + http: + paths: + - path: / + backend: + service: + name: frontend-podinfo # Service name to enable GSLB for + port: + name: http + strategy: + type: failover # Global load balancing strategy + primaryGeoTag: eu-west-1 # Primary cluster geo tag diff --git a/packs/k8gb-0.12.2/charts/k8gb/README.md b/packs/k8gb-0.12.2/charts/k8gb/README.md new file mode 100644 index 00000000..4fb1f829 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/README.md @@ -0,0 +1,128 @@ +# k8gb + +![Version: v0.12.2](https://img.shields.io/badge/Version-v0.12.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.12.2](https://img.shields.io/badge/AppVersion-v0.12.2-informational?style=flat-square) + +A Helm chart for Kubernetes Global Balancer + +``` + _ ___ _ + | | _( _ ) __ _| |__ + | |/ / _ \ / _` | '_ \ + | < (_) | (_| | |_) | + |_|\_\___/ \__, |_.__/ .io + |___/ +``` + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| Dinar Valeev | | | +| Jiri Kremser | | | +| Michal Kuritka | | | +| Yury Tsarev | | | + +## Source Code + +* + +## Requirements + +Kubernetes: `>= 1.19.0-0` + +| Repository | Name | Version | +|------------|------|---------| +| https://absaoss.github.io/coredns-helm | coredns | 1.15.3 | + +For Kubernetes `< 1.19` use this chart and k8gb in version `0.8.8` or lower. + +#### Compatibility matrix: + +| k8gb | <= 0.8.x | >= 0.9.0 | +| ------------------------------ | :----------------: | :----------------: | +| Kubernetes <= 1.18 | :white_check_mark: | :x: | +| Kubernetes >= 1.19 and <= 1.21 | :white_check_mark: | :white_check_mark: | +| Kubernetes >= 1.22 | :x: | :white_check_mark: | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| cloudflare.dnsRecordsPerPage | int | `5000` | Configure how many DNS records to fetch per request see https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/cloudflare.md#throttling | +| cloudflare.enabled | bool | `false` | Enable Cloudflare provider | +| cloudflare.zoneID | string | `"replaceme"` | Cloudflare Zone ID follow https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/ to find your zoneID value | +| coredns.deployment.skipConfig | bool | `true` | Skip CoreDNS creation and uses the one shipped by k8gb instead | +| coredns.image.repository | string | `"absaoss/k8s_crd"` | CoreDNS CRD plugin image | +| coredns.image.tag | string | `"v0.0.11"` | image tag | +| coredns.isClusterService | bool | `false` | service: refer to https://www.k8gb.io/docs/service_upgrade.html for upgrading CoreDNS service steps | +| coredns.serviceAccount | object | `{"create":true,"name":"coredns"}` | Creates serviceAccount for coredns | +| externaldns.dnsPolicy | string | `"ClusterFirst"` | `.spec.template.spec.dnsPolicy` for ExternalDNS deployment | +| externaldns.image | string | `"ghcr.io/k8gb-io/external-dns:v0.13.4-azure-ns"` | external-dns image repo:tag It is important to use the image from k8gb external-dns fork to get the full functionality. See links below https://github.com/k8gb-io/external-dns https://github.com/k8gb-io/external-dns/pkgs/container/external-dns | +| externaldns.interval | string | `"20s"` | external-dns sync interval | +| externaldns.securityContext.fsGroup | int | `65534` | For ExternalDNS to be able to read Kubernetes and AWS token files | +| externaldns.securityContext.runAsNonRoot | bool | `true` | | +| externaldns.securityContext.runAsUser | int | `1000` | For more options consult https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#securitycontext-v1-core | +| global.imagePullSecrets | list | `[]` | Reference to one or more secrets to be used when pulling images ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ | +| infoblox.enabled | bool | `false` | infoblox provider enabled | +| infoblox.gridHost | string | `"10.0.0.1"` | WAPI address | +| infoblox.httpPoolConnections | int | `10` | Size of connections pool | +| infoblox.httpRequestTimeout | int | `20` | Request Timeout in secconds | +| infoblox.sslVerify | bool | `true` | use SSL | +| infoblox.wapiPort | int | `443` | WAPI port | +| infoblox.wapiVersion | string | `"2.3.1"` | WAPI version | +| k8gb.clusterGeoTag | string | `"eu"` | used for places where we need to distinguish between different Gslb instances | +| k8gb.coredns | object | `{"extra_plugins":""}` | Extra CoreDNS plugins to be enabled (yaml object) | +| k8gb.deployCrds | bool | `true` | whether it should also deploy the gslb and dnsendpoints CRDs | +| k8gb.deployRbac | bool | `true` | whether it should also deploy the service account, cluster role and cluster role binding | +| k8gb.dnsZone | string | `"cloud.example.com"` | dnsZone controlled by gslb | +| k8gb.dnsZoneNegTTL | int | `300` | Negative TTL for SOA record | +| k8gb.edgeDNSServers | list | `["1.1.1.1"]` | host/ip[:port] format is supported here where port defaults to 53 | +| k8gb.edgeDNSServers[0] | string | `"1.1.1.1"` | use this DNS server as a main resolver to enable cross k8gb DNS based communication | +| k8gb.edgeDNSZone | string | `"example.com"` | main zone which would contain gslb zone to delegate | +| k8gb.exposeMetrics | bool | `false` | Exposing metrics | +| k8gb.extGslbClustersGeoTags | string | `"us"` | comma-separated list of external gslb geo tags to pair with | +| k8gb.imageRepo | string | `"docker.io/absaoss/k8gb"` | image repository | +| k8gb.imageTag | string | `nil` | image tag defaults to Chart.AppVersion, see Chart.yaml, but can be overrided with imageTag key | +| k8gb.log.format | string | `"simple"` | log format (simple,json) | +| k8gb.log.level | string | `"info"` | log level (panic,fatal,error,warn,info,debug,trace) | +| k8gb.metricsAddress | string | `"0.0.0.0:8080"` | Metrics server address | +| k8gb.reconcileRequeueSeconds | int | `30` | Reconcile time in seconds | +| k8gb.securityContext.allowPrivilegeEscalation | bool | `false` | | +| k8gb.securityContext.readOnlyRootFilesystem | bool | `true` | | +| k8gb.securityContext.runAsNonRoot | bool | `true` | For more options consult https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#securitycontext-v1-core | +| k8gb.securityContext.runAsUser | int | `1000` | | +| k8gb.serviceMonitor | object | `{"enabled":false}` | enable ServiceMonitor | +| k8gb.splitBrainCheck | bool | `false` | Enable SplitBrain check (Infoblox only) | +| ns1.enabled | bool | `false` | Enable NS1 provider | +| ns1.ignoreSSL | bool | `false` | optional custom NS1 API endpoint for on-prem setups endpoint: https://api.nsone.net/v1/ | +| openshift.enabled | bool | `false` | Install OpenShift specific RBAC | +| rfc2136.enabled | bool | `false` | | +| rfc2136.rfc2136Opts[0].host | string | `"host.k3d.internal"` | | +| rfc2136.rfc2136Opts[1].port | int | `1053` | | +| rfc2136.rfc2136auth.gssTsig.enabled | bool | `false` | | +| rfc2136.rfc2136auth.gssTsig.gssTsigCreds[0].kerberos-username | string | `"ad-user"` | | +| rfc2136.rfc2136auth.gssTsig.gssTsigCreds[1].kerberos-password | string | `"ad-user-pass"` | | +| rfc2136.rfc2136auth.gssTsig.gssTsigCreds[2].kerberos-realm | string | `"ad-domain-realm"` | | +| rfc2136.rfc2136auth.gssTsig.kerberosConfigMap | string | `"kerberos-config"` | | +| rfc2136.rfc2136auth.insecure.enabled | bool | `false` | | +| rfc2136.rfc2136auth.tsig.enabled | bool | `true` | | +| rfc2136.rfc2136auth.tsig.tsigCreds[0].tsig-secret-alg | string | `"hmac-sha256"` | | +| rfc2136.rfc2136auth.tsig.tsigCreds[1].tsig-keyname | string | `"externaldns-key"` | | +| route53.assumeRoleArn | string | `nil` | specify IRSA Role in AWS ARN format for assume role permissions or disable it by setting to `null` | +| route53.enabled | bool | `false` | Enable Route53 provider | +| route53.hostedZoneID | string | `"ZXXXSSS"` | Route53 ZoneID | +| route53.irsaRole | string | `"arn:aws:iam::111111:role/external-dns"` | specify IRSA Role in AWS ARN format or disable it by setting to `null` | +| route53.secret | string | `nil` | alternatively specify the secret name with static credentials for IAM user (make sure this user has limited privileges) this can be useful when IRSA is not present or when using say Azure cluster and Route53 docs: https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/aws.md#create-iam-user-and-attach-the-policy | +| tracing.deployJaeger | bool | `false` | should the Jaeger be deployed together with the k8gb operator? In case of using another OpenTracing solution, make sure that configmap for OTEL agent has the correct exporters set up (`tracing.otelConfig`). | +| tracing.enabled | bool | `false` | if the application should be sending the traces to OTLP collector (env var `TRACING_ENABLED`) | +| tracing.endpoint | string | `"localhost:4318"` | `host:port` where the spans from the applications (traces) should be sent, sets the `OTEL_EXPORTER_OTLP_ENDPOINT` env var This is not the final destination where all the traces are going. Otel collector has its configuration in the associated configmap (`tracing.otelConfig`). | +| tracing.jaegerImage.pullPolicy | string | `"Always"` | | +| tracing.jaegerImage.repository | string | `"jaegertracing/all-in-one"` | if `tracing.deployJaeger==true` this image will be used in the deployment for Jaeger | +| tracing.jaegerImage.tag | string | `"1.37.0"` | | +| tracing.otelConfig | string | `nil` | configuration for OTEL collector, this will be represented as configmap called `agent-config` | +| tracing.samplingRatio | string | `nil` | float representing the ratio of how often the span should be kept/dropped (env var `TRACING_SAMPLING_RATIO`) if not specified, the AlwaysSample will be used which is the same as 1.0. `0.1` would mean that 10% of samples will be kept | +| tracing.sidecarImage.pullPolicy | string | `"Always"` | | +| tracing.sidecarImage.repository | string | `"otel/opentelemetry-collector"` | OpenTelemetry collector into which the k8gb operator sends the spans. It can be further configured to send its data to somewhere else using exporters (Jaeger for instance) | +| tracing.sidecarImage.tag | string | `"0.57.2"` | | diff --git a/packs/k8gb-0.12.2/charts/k8gb/_helm-docs-template.gotmpl b/packs/k8gb-0.12.2/charts/k8gb/_helm-docs-template.gotmpl new file mode 100644 index 00000000..94cb75df --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/_helm-docs-template.gotmpl @@ -0,0 +1,36 @@ +{{ template "chart.header" . }} + +{{ template "chart.deprecationWarning" . }} + +{{ template "chart.badgesSection" . }} + +{{ template "chart.description" . }} + +``` + _ ___ _ + | | _( _ ) __ _| |__ + | |/ / _ \ / _` | '_ \ + | < (_) | (_| | |_) | + |_|\_\___/ \__, |_.__/ .io + |___/ +``` + +{{ template "chart.homepageLine" . }} + +{{ template "chart.maintainersSection" . }} + +{{ template "chart.sourcesSection" . }} + +{{ template "chart.requirementsSection" . }} + +For Kubernetes `< 1.19` use this chart and k8gb in version `0.8.8` or lower. + +#### Compatibility matrix: + +| k8gb | <= 0.8.x | >= 0.9.0 | +| ------------------------------ | :----------------: | :----------------: | +| Kubernetes <= 1.18 | :white_check_mark: | :x: | +| Kubernetes >= 1.19 and <= 1.21 | :white_check_mark: | :white_check_mark: | +| Kubernetes >= 1.22 | :x: | :white_check_mark: | + +{{ template "chart.valuesSection" . }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/charts/coredns-1.15.3.tgz b/packs/k8gb-0.12.2/charts/k8gb/charts/coredns-1.15.3.tgz new file mode 100644 index 0000000000000000000000000000000000000000..88c88c71b040a3cf168a61c5e7d58517ed04dfa0 GIT binary patch literal 12345 zcmV-9FviaxiwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0PMYOa~n6ZFuGsw{E9wQc5UZ~LsGJ2FHiYaDY7?Fo!HT}>}>7z zNk!lcNMbbuOaP1|#`5#qpF#teHx4O@q~-X8ld4#p!Am#L=x%g38j+AR=Bjr*B~pho zk|uxI_|xzA`-e}T;=lcVzxi+f+2HA422Tfjdx!f6hyAC2=@0e}_xJw-{mp|i|Kv&& z`Ir9MeKnE$N*=}M(!6MP7ldjZL^;^!cI9`=Knsz|a-B~1~z!VTLe<&(1sRTVG z*eK%)vLv6Fe+iEvlj4%aRKb7eBPu!7RAIFkmS*-v!qs2{S$kF6it^$XE@7F1Wfu7wrEp@)7<{3FDeD zP9+xO#6XhDoKA{gQ$pgv{^?s$B9{@x8XmX_!=aBv>f!YN26~p!A&@LfScDT6T$ZCd zI0*NHRp#IKa!Hb$s?Wm!maqT4{?ljA8tZ?5&>w8q|3f@G@RE*6o@lTX0AnFNfrh~j zyqhv*m*~HaUjNt~3z-tFX$)hQP*dO~jS?a$ToTF1D4`0pfDwg^C`DsnTnm_qT!N-) zmJm%<7zDWR48M^y6N+geXT`E82p&L_$q+ioJ30YCmM6)nNLVx*!pZoJ(5I3r%5@M( zimT#S`Bv7|&( zDEY;yh>vnDR74UgL5%)QBOL}iJHZYR_nz^|FxWB8G5*#V8VN8@hI2T~*k z@%LFwG){X;uHSQVNmyb?#^8_d&T=`SL)bg`YY^Q%WvpkO&e3)1b)(Rgelv zt(;Jr@R-OLG)t+WJV{e=N#Rt)KzW=A#x;zkNP$3<RlkV6jLyvoJwLCX08~YV6AbUB>3I4#K5mA?1nVv++%eVMabU*fCxEH zIYJ8|b9D?c=Bf!Ns#Ufr1FD&=O@l5+BpUi|Z3nKyzZrnw?RQ7V1&>h`%uLzVdIn}w z^As0LE}5R$NiqULWv{s9DEAzh@be7KjvXAs&6sj4&h-x}qY)c3s^DsB7KU{Cw3>=M ziH!)2X_kl?je)3Q)jL`MA%PoNoWR9%WwgRDX!hU+G1!5hGP`&nlT4TqgD4@&OX}Rn zX(RRx7EbsY_NPL4??08y2H3drEA%ZMn+D$)^xX)C!Q3aiMoW$3cfoNquM8)zX!Vjt zB2B5`gTYRr8rPXzEF#s@L|v#JiBrZIj*c6pUd&ZD%9R#r7dZs(EL3mDVb_fWAG1kH zvaZ0PQGqLBba4X~ayI+t5DalxhIO!iuy20YZHX;o$)8Foq{1mT!%vOI)SFV0=xHg4 z1c%}C{`3AWDjH0>!A;mD&7LJC z@vPDD;Q64@u_?vcddBM5uURyC$LA8`>bEx)1{12O})EEnSMPxizJcJ(AQP1$gkCk z2$9uh&OEni*0z z>bY6-sKdK4^BsfAGlQ}MrvJkYd3DW=g@6%}rk{i9v-`EhwdD33c^%u}CsA`=BY6v>*svKY;6}c<10WOZ}Z4Nz+wL((K|ZC!-t?oYL6q z1x^pIOy46v3l^ZD)|`=sh3f9qH)hR+FU=;a*xDQ#ww2YlI|K91%!|l%@$w)r?42dK zr0=GZs;Nj~`&Q*qM3t(%9n=x6OSawO-E1{P>&@L6)BVqbDQ;6T8W|$xS#Ea0GLN*O zW}-}gUbnP%!ettiq+=>6k7%z@X)DFLBxAkHK{y!ncFcB&Gd=5G4!TB-3U+X9I`Lu6 z1HOzm7H|>MqsF^Ju)fSCktC#CY*>G3x-_~>P+*Na z9>a=b3JLC0afmWuGfoiR&{ z+G(ey#T~KNA3W>z4|@IQJ-2x=dlkyHWK?y>LUv1BdVy*3AErfTxqvQq;I<=nBEooN z$1D~pVZ3}FiPV0G1lN>nbn!Uyu9PwA*vT6>`{@W2S0Ta~5zg&5E~4hEz5d{!|9tP@ z=>VSX_4}}Y*zdz&umAT$_hWGmwJ`ex? z_i)hP^JTvcYo*)E2BppeL`pI&;BXA8zj$!U>O(JT}^Q-KgR;iZHNizhdYNc6Q(>LA#`8m$cw6mZO_N z{o(Y;S&IxXrnM`=HI0LvV49JdzTypI4gW*K`>+?3t_Kf-MJ}hMDZQIXVRTlcl!`&R z>O>06ew(&AI4iP+@hBe|=HI)e<)Hl2niXF;-3@J5x73{*1#IC>o{p$A6mB3kVzk;A z@@h}w&dn5nEqY3&8?hnm9UL}VGot#Atzpq>YXjTZYqKq2zvFJE>f*A~Hw0_WculTb zOTlBeF*6_fz!Y#{X8DPoY+wDK&ibeYFeFV1IagM&n$fBwf##fjxWX-Rp??1rqp|V*({$gzyOBH8pj$B!Fu5Td9UjGp4b6s0T z4c5R`ct)B=_)Nq>>6}%bgsa|b=fCdk^;7SI^DgYpp#PfLmsQ{R?KLWtI|ou>QxBm0 z+cs?ESLqpQ`Wm_m8bK3DNJBFxMAOMER2k!(Tu@w@j=>mi?p&N^?KrDW(GD=hA8C-N z7sqq{OQeEQa-#e5f@N0Jm29ZF+b>*RUpjna?WfR`d~`*17;{Wyz z_6{5IKTr3c_P6mr5Al5b*fnw^{Mp8T&3P$5eF`dpdR$zA%sDsOYeTaks-hPKJ$=#n7#bN7 zqVe`a|Cf+E7(R8p-$i5br67PDxmX?17P?~F-o0sDr*D&VW7Bu#&&u-GRB0Mp^8f}|2&4I909`N$ z;YX75XbJ>ly|9pBE?S604THeXl*~DFnOW8{HUFcA-Rl=`%;p}tUEBb?V0Gn`}@uK|AW2#t^9wG=i|rTw{XeQA-b-|ETMXq(HE&1mS{?c@NEwlXz$zL)pbU= zwX{^@sW56O3|zS`#B|Jfg?(7o(JjBCNg}idPH^+;Ig%;)(>4`VvN6Lm%-m6^oErc~%@**sd1YfHq{2wu=|E^ht)9SRT=hOsYo0EOnfs{{ zS%o$ljHapu4Vhi653j00*#L(AR>ERQDReNE zfJ)~g*G1r>0un_+q94-%VRlgvi6o(sVJl=LE@_*D!@hSL1LWXpjs+XTqH%8>b+4Or z;iHe(-gSqQPVx6&FLw*JIW%l;*BNv3IP3mZefl5X@q<&a>DwrE0gy=Y8vyd%aRH=` z?hWLZRJDqbfUUB%RkpUu)>hftDqDXBWlL}v2|Y#X_}f>bdaXCOTg7c-id#)<_`_*z zOQHLms+u!zHqEaE*R7xQz0LgPj=#QHWPz*~3*AxJ64GMXKlVXmZT_Msi`qjBnr6vH z%N_T}oLjNAk(P1$(zf-l;hFdUIRBg!39aTBSR*scZSf!b&G?VK{@$~vTmR2PJQZQ= zS6OA!{mCf*NsdV5dBLYoLATqjC4IurB-c|RUH*^o;yFghT@Hc^#^WJ4PxM=n&>*Fn z#6)9!vSpfg@ITiBdTq3zRi#OmH8NqOgp&!4yQA5#=AQS#EjRF6E_9)6&Nslg(u7BJ zIOpAO)}7KM4b`-V-moEh(yI=YPoKKw8#i8XgW z;I}(8*Jo3R;OsO2xHjLRdjfcSwtP;q-gCXvB7|#-t1qfJn z)cK`4^Iw{)em&1p`M;rbaJR|-{$Q^W|8Y3j+sgk3d0OOu$xd#Q{|_zuw*r5Gz;D3z z$CLJ67FQWQ@_$SlRXfMfEy8;h{_-)j_#+dsDw3LDWHuwL7!~L!Ne~{-3?*G5D)U`DOY|Q|l z*9;&M`j(C{y}6UdOGq^UnAcWUButfK3SiWGY@_w$ldBVaCGY8?^B8xN?RVk->uv*Y zOM&%q!TFx~kY*NN@4`2jo_F}d zpP=~k>ElNOu=(mTxVR)n<}d8L8mHQ^4Y+{*#>dcq#Xf8cwyn@LRt^6(ql9t7pFR!E zG`qi{Su`jkh#jUrZ+CR*nj%8 z8UH&NZ0)}f@>CDwEH(nTgE+pxG$ZAg7LiY~OqFKeGE4G?tpr;m!T)k2!DrGNR7N9v z(V@!)i}2zF5}AeZp0SjOS+M$tWtpbV!9V%_d~7qZ03ecP3zC* zoy=8Et+|`U>Up#A`n=BHvI+J)vdYtPla8SKBUq2|oEm%+zH>tpen%8NC3*^-#diJ9 z6A0l3)RgQU9I8BBg7dPecIF5wLy}}u(irMUGE61V%|tweN007Ut(Fz}(T9(n3p(oz zJIAiIqc|2^{lt@5XBRsD29eIN^Xi%@tva86d9-MRJrlsc=NvsN2qq|wZO&!qu4dVC zBROBF)kf7U)MPF#ofSn|5`cgF*jA&JbIs}R?PgS;#k)ed#f3lfE1|7o!KRMv!eMLmRa!q z4s=mTO(um}QnY?rNqN7la+w;x%0VhYuuI3O%!*#_Kl{~&B9W$q$0gr1<8tfO64k<$ z#I7%vsF~FY1%G|966^5I*gP;VN~O7X|HHNw+Z?a41m8&_CR!*RQz>7#l;+jXmoN6V zyW~H|vuyvrDF?vv{r_O^>0Zrt@*Yp!;(J+r z<5iZFT)*c<+WUH^)$(DzU@7TSa($M|$t_i}hy(TyZVb77ld?LEKDhZ~fpuXswvV+9 z9vfP9&l{`G0d)tv#tKG_KdB|7fmJ5rqk1&c{A4xCES;{Zk)+X;rV;~&nBd<_64BG@ zHOG~m__AU(=5)sf=LqV~#+xPKye;_M+pw~@;=S!Fi-|Ml%I~jVTD9t~c8dGiY1T2$ ztYVQ_*9^0o?PZe&7f)uLW%ia^j4b!JtSmF95IIpp_y8R=O&GRPyBpOQ|XA5OYy`ijK zqL`<7A^*ZQ>ILhK%-_|&u$gAjdPD9m)4Md(EP9Jd+00l#Nz9fKNWH{eDa6#8wGqhR z`Cto8i_O-S(!!}?W{p0jh5Dr#*Ok2li8hfXh7vNvM9r%V?{Qq}aSTJN1-7DMi?VZXcNihM|F9k~0%q*jPl(^S

sPj40 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 WVmQD10tEv4`g(XVG6Hgi2Kqnj4Q09j literal 0 HcmV?d00001 diff --git a/packs/oam-app-controller-0.0.3/charts/zot-0.1.50.tgz b/packs/oam-app-controller-0.0.3/charts/zot-0.1.50.tgz new file mode 100644 index 0000000000000000000000000000000000000000..e40322a5b095ffe916e6f479ca4fd9f297656f6f GIT binary patch literal 6690 zcmV+-8r|g|iwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0PH>cbK5qP`I&#k9_8;G=PX*5U#V_-Gp^${>6bXZ*iG+ir|#t{i%u~=YVzyf^F)yBb;2o=mp56Jc7ZOL8qQ_sfc(q`0Tcto%;t# zBx7%>kc_7zm<>IWWzJ(T2!?$T4!wxVP_Rtt_xtdi#tDQtYhcU;{53zLBBhE-FC_^b z!F#SeHP7e>NS4JcBv{d#6@Ul9X0S8xzIN9i(xXR@kpE{S&Z+!z0^nx;-`w8b-f8mx zaCi8?|M!u4@QjX09xE`jKr{4vt^%(Ir&A_@Ng(jI{Z}vhV=fY+6pdiaVu}Tx(J&^0 z!i)$;&SEM-aX6!p5h-Z|EL9xlJQtv7lEp+(8F+$fiEzO4RE=QMV+onikq01X#wAl+ z%ttVph9Y2mBNO}&8md0d()V2TW0vNZeUe1G+a5rc$MG?bSvViTi}4Xx$AU_lDi5Fs zuV+*U79mbk3c3|gWC9mcE-6H|)68TWSyl2W1z9*@ev5@YEp+;UebCS`J zjTx12F{Nrs1rV_1fS7_Hr#z1%BupqMQ8eBB+!|dRt@!V-m|ngg7s?HgcM+9fUEFas=swrI#JW zR4n@>)Ps$4#V@9lnI5{GASj9Sn+w4d1;rA|b0sw} z4I?Pfskfd9emUwE*x7B&^|#RxW#yJ9(lUw_km zfIiL+L6yO$2CuJTLsxLx?iKL5n(o1O^FltZJGLD>KRrE$Oz<-*QIweHRT)lcLRSMg z;W%GUU!EWX*%|2dfTa-fbj&8X(6m@b?#l$7(Nw{hus9b~t{cYHpdiVmLSZQlr>|YPoAljx-935e|7OSwsbDuwx#Q!1tD69}qukxH)z zG7m#4B?`KE0MGdaol&t4k|z}Bfpo1}2`Qx!iXVoLBt}6ZRG#Ts4LtRF*ccNqW_dvW$B586Tu=x}3M7vC1p@JUZp&KSk#h?4QVC+3L*-p>0WO%D z@?1g4lT7f0X+|9rsk|NtDl?u+il8D&qL_#0GVok1klGgFGa8fm2@QD~$r0?}e5Zo( zsC>1Fg53`3=~PfT<#9BEEl-Px1l7=io(hGkF}hd3dPOp=MIu-^c)tJU^xd1omxuc& zhyAdup#kVQg`J;L$au6WVReJ55Uqn%h?t-uS`ePoSRn;(MnW3^MiCm5V6_vE)peXb z42c(UDzzG=mrN>MCzn(pSe)}yA|_fHCnO~kBsx>@m`Eep(SkyG80ToA5S(sgkHH@jeZUWWE!M8A zaPy_&f=sACf-CR^=jvH8mi`F*jTsReF+1B3bi$+(b04nPi>fFWOg$1sD8{kIAkhE( zb@0)Qz*lH_xb>5?w3?zfWVXAZwBJ+g0OCw@*)kc{M*A6BKAatl!M+(3%-2_Hu zGZVmn@}&JzV;i&3)cCcP3*aN?>P-F1|82da3<)O?b?^=A;;%f5>@UON_3k)ml|P;Nas%)5OdYRR z3MezXrBP&BTIfk%=ELKJ60HGIN@;mXBRHEIQK?1qn%8qRyR;BdxiO;*e&ML&Qbkxw zh4EggEvH3tgseGc1~6Kr+J||Z37%1*=HOQ*l)t8#v~=6N9vUp@S%Pg$VqF9vGZNB3 zw^c#Xy*tL~UidOrryvV>Js0Z|V=egQTq>HNry-~n;RXIyJ{w8!9Yu=(J@XW-@isCd zqCxVJ*Rl?6KR10dP$jMvXUYv}ayu&yZ>%`T8F_orJ13xCVeGW*CA%-+N^@#3vu+jF1hA8*w!ov)0)wopI`#4 z1DOz(q8Z`!w5Giv#ydCj9u+&n(K-~Sq*ziRQADH43LrDiDyN*G5~rSnnz8Z^&D?;Z zZ>IaJT3n3u-&Oc`SVf#i_-9q4Kf=P05hl=cDC(9f+tgke&Q}IIE3<^<;yC$n_Iw_n z?>&9~{QIACk$?aFTY4Nb^^N%D=O6YrzCZhAe0rE1y-Dd0KdLFwV023s%FCy_@BjSo zXXEEP^X=`OD0~%PMf7+gdW6%C6(Ytdv&HWiseEy$yZw@#_E5fur1cwG|$dL!qC$IQ932e= zmyk5aibgHb3PE13@D%Hb#d8mioW($-iZ#-?DA)U1WGSaRs}=~+??iBBPIiq|L6UME zP_Kbu9W!|fR!Mk7HE1KY60VgTNl|uzT^2^m82Qr!Tk92%Q1`r{B>Gt}MPH|(U3EHP z@5}z#$tdWbIhAIC)eg-Fp8mjE^st#`6{nz#cI@=(9~+OUKy|Ot!wSV5MllPuVLz(6 z+=G{>2KX3gI%9&T3Bsr?jw3~RL-l(!ouQ)c7t5%phbO06%W9gBz<+hsMXywCiI%6-fzfaKG#&0N)SaSbG;ht6;IW= z^BW$=ES>zMja&pK+!vNE3Ay|!B{RZe9H0>lcmCpe8ISfG%cWm?ljaMi_grn1yE7X{ zuTKw80(GhGw2fu^|GPWG#{S>d&T#W#|L;E157Zhq&cfnPZ(gF_F02kUr4q$el8`i# zBk$^}kFv6~a{OXn#)sgoS^BZ&M4)$WuCG1Nn;t^J(d%c2?~Y%;IsJC!@p*nmLlwh> zD(Lr1ZwjuiAb3M#N+b=A%D30o(C6@nN=YV7Y??-Jef?#|zs~>frZh&IAW+#Ih5{_%|E;af-3I?}Z*M;A|KCfxy4rZ+ z9bRT=S*pesvNnbT@5#pXwVsE1qr$S1VWWPPqs^nhgpz4ftB?g)ve=A=59s!%A?$AH zpDa1a$76O0e%}WR%glDq)0iC?QSlP}eWiJsmR|M-qsjW}}kYU1TQVv0i|p@a*UW%c3MiiL(}XFUBB@5U}1!AqkE5 zU^dT{+4Vi6#$6!jRw42h+fJfZ@~I#!8<%t}GD}+8A`A0xL+eR~rm9cu>P8otPAu{_5~|t5erNN>dudXqGB`S_uv99d7ciQp#Z9xbDX6<+eHL}a z4PrW4ByH-&0=s0;5ciK4SyyX|;G}NP9R4mK7TYB)Q?e64i-*6qHvPv-b^FikFeW6s z(_qkL{@>P4%l_LN4j$~k`$(4UQOOk?=f+4B@7#C+Ey$dx@lEfXrO^luia-u8p^8LA zkx{uM*dg6)M1^MxA|8UI6ACNmbiNKNGZLdQvH$@@gy;b3>W!T&p(TiXx(e;>)^WRhiaqh#l5v9+6@Z&+FJz*6+gJ}BEE@|Rvyez5IIIY8BgYFF&^P-qrLj<~3hQilRoE0({BIqS6`bpaI2yny?fd$ zQ})s6$VZF+qINi?;knEcYd6%U#bfR3z)Emx`yG5oBt0f-3Vy@R@YgiXa!Q6fyE0F1 zhjZ!oauL!uJdWKmg2%C)r-G!>ewrc`=zgM^Yb1IL_lT zIHqj8nKSx`F>dvwZSA*tx6304To5Mk{D7y5UaD?%s`+_RFW!x3x%X9zZmvuP$1irq z=>}XD;3F3zvpK9oHpfuFcjS$J6;#Jk(9~#UD>8u(%_WnXx9c}sId+b%wBS`|TI%@e zJ;EiurRnU39_p3yI*fwk@42eIcLwO#J+$GbOmM|R9*^Mk;Ml9<#m2w|JWjcS$0lT@ zM6tP4sSA z#>e*kW_)Y})UDC6yTG?V$C%`|qH+T(Y`1*ulDbVKt5~z{(zhX*J2h@5Su0fK*2FWj z={AVf1b%Dgx660P_9hcAY^(LMINeZ2@mFbKJb#s(vlec$=TBzCjb_FoF;SeZ45 znm5m?ETOp5lv^|CDBMJ#aoA-Mq*}2ijP~J}MPQmGn~)wR%O^3Y{B^Suz z%F6i?*2@yhNv^Gxh}iJLk=Hpi3rw2+$CxVR`K&t8ZV90^4!1LMZo;r-y_gqu^xVkx zr9e87ytV1m?>1tZj>}RMyXr0@-vWc@Ci1oHm(F0{I;tVQsxU1YpM`;J_$_`AIdX375FaBp|eivQYr*#Eni)X*oz1Sl?WR2{tLVI9`}~-TNC=ms=YeB+C}9Q`*3=#qk{VRbY!aX)fy5wgaxNT-ogITR1|w zSZ!V~pyhoP2EKjmoM3QQB3pH83o?zZ)sDtgY`dWh#foC?@Rgv9owXQ7-@P-#t)O35 z3aYQWP&_x3<1$;Txm{d_rZgP`7rpvew1K3Nel2o)Ag^sz7SL*4vD8{=QLDHx#O(yp{%3QIEltl zcYh7sviP69t>*oYTRYni`~UZnIyQj2Rw%MrSabWTc)-q3pyMu=azR+oXE~FF)~gN+ zY9Y{XLay>1_>EJAhKCw!MD|EwDO$>7g^dP^6NL`+r#~>i;!D?QugV|P)pGk_VRti) zYM&A8ROf%A7VlaFERFx$+icqZ!>zps{=bj3C;+6fYU$p3u!!kRm0Je?+4VPbSo3v8 z{>W258z1dn{r}D3PBZ>*dwX;1f&cF#E#PExgXX=( z{j~%6>_ogn$5<7n{o+Ha9m23ER9^83kAeQ#4Z|<*1ogo#bvrkMcC=gpZO0%w;W~Z0 zd)EOWt2qOThzV6DWT%Sh>59~8#{G1k{wNRC))&Q(7h%&benVL0M+MbwKZxuvlRD+U zJx6p`YG9fDx4qX~|J~W!eX#%TCEe=SS93|VsVHpmTj+}$Vog6yb94oP*ZXj@3W1M_ z4F4xIAM5Ry>lQ?539c=}hPi=<1E~Q$Hm(%iRKP-QKDA#~Zu+_Kb zCf3@%JR76Mxw0TS%h%Uq`}JrO2bQb@Ys5t9>qq<*Q=!%DvOuc~dvy!%>yse;kP5}d zOkcs!=fHE7^j7GM#wR&&M zJ%rn!e8-4((_K&<=T{s6IHEHuzM?j{h5Y|)GjOT=A2#j3z2SrWzn}EwA|L<(IzyCFS*#Etk)PrN96cy$x zN@fz6tC7!g7Dp_dKt{rIGNH2kB$&)Iy*deUO5+$NF+Vehq**#y2SH=~!2}&o;k+kl z6LZPn<4n*oyDVJvf1g z3F!qBrZ)6ngT5D>y%!t$Z}DO}*}y-=qnxE16`(T`p6B+0aPLVVFEZ~*a7NC(CxJ@v zHy3Q;J^4Sc2XBdBJeTm|*`f3T`*kueU=bx7rnumLc)?7DJfa)_2#W;B|9Q%kvHae> zlPSsMl&g2|ieS)pn5AvN05dY8zANaToV=y0c zL2G7nWQ~@k(Un-J9$^W$z4G8zUnT1*+VN#F=s3!+LpR;?&Sk)6aiz7sSJ~tlqtDIg z7ggQE{q0~%jcC6#Qk@vU!u(tI=`U!+x0%%VAXovcBQC8p2)p9bigZK&nyD*btpsBO z*E&v@f%D0-_WRSDzmn-m?cG$?aF^&`C2E;*1(-JXax4^w(y~_RQ_=eQ4ZP<*6c2 zuMbR(^v6?D-n^v7eA@t=LyG0aJS~8jOQfXE#Tk8I@+gmER|Xjor>~?A~ue=IZ`ns z898GyQ>+q-3HgJI(%acA-m=tv`^_iyZqpH{e`R&^osa9jlPR@-{Gw>IQFehF)!K%D)q3`q6h)Vy=$s!HaB!N@PUN%wdMU9NhT;;nZUsdK_+-2u@o9lKh`@D3K sKFU374Xvi^i6!g^uHc_1%;q6Iq=)p7{_fKM2LJ&7{|pCY;{c2R0K1;{DF6Tf literal 0 HcmV?d00001 diff --git a/packs/oam-app-controller-0.0.3/logo.png b/packs/oam-app-controller-0.0.3/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9e5c88235cf14a6f35e8056b67863061bb241dbd GIT binary patch literal 1757 zcmY*Zc|25W7(QbVlP#4kZqxWBlo@*rGnPAQCT1*Y>}u?T8Dr+SW3sgn3O`G-WNlDg zk-BA1WJ)4wFRmq(B{!6ANkjLHT;2Pf-+SKYd(ZPc@ArOxoKz>uURi`10ssJ65|Q8n zWpz-!8k5^ZGqZ8^(knR80bz4B9j4K2ulGHFhu|^qCgJ-Qv)PcFaYd> zZCS%EFzr>27yu;G0r6FiCzM5t2nD2G&G0hVPscK`HMV*g{3jO4@{$Y6p(M>BdT;<> z{YFv1fWjgb$jyW9>JGY-9kBip3^Xku!Y>dV&0vXCfMqlmf{Z|rhKy!}Gdb939BPGu zg|MiMK_OQtU>FYNPIf~68o>@knxgg5`Y1dCi9}km1A?$FggvWrXoo|EfFKKt!Em`; zG}j0n!4Ae4n46np^bIkFhI$Y~kHcevv}iphNAritzdnROjz62u0_hP-j_RH0Gv2usY`wc!z}zOU8+fOtBIVB<=ZeNQDjcpun=|I)^T>-FnC)g6^r zQaM!Rw=q;1-J72e249N|b#MSHPce-jUbvzYafCq5Q5$3qG;TBSvG!JJD5RJ~^2O<$ zTgs&*bo%Fv+I#1W=7%jxI3q&Xyg(4*H%1;GD&@4z7st$+Psp`@XADZ00r2gg_>x)i zvYF%GiJIAcyAz)E3}}tj9mQuaZU2bNec|4#K+SM4jsvGR+^p3gC=~SWSsWIe?{f1| zeQ#=rq>Wzld3L20=D2OE+v!%*#K%E`EgME<_QjHjH%L@h*npB*fvcLj5GD~H*)l!p z7QQpwd&j!c9*f4F*smIf1quR~LQ3JR6W7M-lUYDsRfu-HSi8qI0iGc9HT0KoUPITb!5R-*N>OHRpaZ@}7~D;(;ds3unA)ZlK`D*-2* z(;nSAhfQ@nR;ov{e^P`{)qJ{7(3~(}_U59-l!2ERj;}Ilx_gk`8+Kng!p)k}$7v{M z@t>3B*)yS&Y&H0uyW7vqHubcM!EN&%y%=D$-EZIHe>FSi!5to{=CzQu*}RD;pp<>d zldQbi**$hf$H}Z2d)cW?I#RdA^7`B7HF(LPqitzoF>#djXCrry#ORW5kN)oaEnguc zKKrRf@VZ%osj(7nbD5~ z^C1+ifBUsq_nk}MNNx^BNSQ0=DCX;%uD`f@3+zyrm~U=%o^B zTFMIU*TEX*lpJm#61o%NSfcFRy5~pyqL1#-d~hObxoY(u8CWt z$k-{(y*f4LTJL0>UU+K)R!iPccyR4=25qp5+t^y{JYZpefI0lcVp)4iCJ9}e#S|9i z1^QyVL->(5t|H_(9rs;tEw$P3V@5xXU9|E8#!9=v{8UFB9oedhTy<8($&yb`V|3 + # secretkey: + + # Enables podMonitor creation for the Prometheus Operator + prometheus: + podMonitor: + # -- Enables podMonitor endpoint + create: false + podMetricsEndpoints: + - port: http-prom + relabelings: + # https://github.com/prometheus-operator/prometheus-operator/issues/4816 + - sourceLabels: [__meta_kubernetes_pod_phase] + action: keep + regex: Running + + zot: + # Default values for zot. + # This is a YAML-formatted file. + # Declare variables to be passed into your templates. + replicaCount: 1 + image: + repository: ghcr.io/project-zot/zot-linux-amd64 + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "v2.0.2-rc2" + serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + service: + type: NodePort + port: 5000 + nodePort: null # Set to a specific port if type is NodePort + # Annotations to add to the service + annotations: {} + # Set to a static IP if a static IP is desired, only works when + # type: ClusterIP + clusterIP: null + # Enabling this will publicly expose your zot server + # Only enable this if you have security enabled on your cluster + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # If using nginx, disable body limits and increase read and write timeouts + # nginx.ingress.kubernetes.io/proxy-body-size: "0" + # nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + # nginx.ingress.kubernetes.io/proxy-send-timeout: "600" + className: "nginx" + pathtype: ImplementationSpecific + hosts: + - host: chart-example.local + paths: + - path: / + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + # By default, Kubernetes HTTP probes use HTTP 'scheme'. So if TLS is enabled + # in configuration, to prevent failures, the scheme must be set to 'HTTPS'. + httpGet: + scheme: HTTP + # By default, Kubernetes considers a Pod healthy if the liveness probe returns + # successfully. However, sometimes applications need additional startup time on + # their first initialization. By defining a startupProbe, we can allow the + # application to take extra time for initialization without compromising fast + # response to deadlocks. + startupProbe: + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 3 + # If mountConfig is true the configMap named $CHART_RELEASE-config is mounted + # on the pod's '/etc/zot' directory + mountConfig: false + # If mountConfig is true the chart creates the '$CHART_RELEASE-config', if it + # does not exist the user is in charge of managing it (as this file includes a + # sample file you have to add it empty to handle it externally) ... note that + # the service does not reload the configFiles once mounted, so you need to + # delete the pods to create new ones to use the new values. + configFiles: + config.json: |- + { + "storage": { "rootDirectory": "/var/lib/registry" }, + "http": { "address": "0.0.0.0", "port": "5000" }, + "log": { "level": "debug" } + } + # Alternatively, the configuration can include authentication and acessControl + # data and we can use mountSecret option for the passwords. + # + # config.json: |- + # { + # "storage": { "rootDirectory": "/var/lib/registry" }, + # "http": { + # "address": "0.0.0.0", + # "port": "5000", + # "auth": { "htpasswd": { "path": "/secret/htpasswd" } }, + # "accessControl": { + # "repositories": { + # "**": { + # "policies": [{ + # "users": ["user"], + # "actions": ["read"] + # }], + # "defaultPolicy": [] + # } + # }, + # "adminPolicy": { + # "users": ["admin"], + # "actions": ["read", "create", "update", "delete"] + # } + # } + # }, + # "log": { "level": "debug" } + # } + + # externalSecrets allows to mount external (meaning not managed by this chart) + # Kubernetes secrets within the Zot container. + # The secret is identified by its name (property "secretName") and should be + # present in the same namespace. The property "mountPath" specifies the path + # within the container filesystem where the secret is mounted. + # + # Below is an example: + # + # externalSecrets: + # - secretName: "secret1" + # mountPath: "/secrets/s1" + # - secretName: "secret2" + # mountPath: "/secrets/s2" + externalSecrets: [] + # If mountSecret is true, the Secret named $CHART_RELEASE-secret is mounted on + # the pod's '/secret' directory (it is used to keep files with passwords, like + # a `htpasswd` file) + mountSecret: false + # If secretFiles does not exist the user is in charge of managing it, again, if + # you want to manage it the value has to be added empty to avoid using this one + secretFiles: + # Example htpasswd with 'admin:admin' & 'user:user' user:pass pairs + htpasswd: |- + admin:$2y$05$vmiurPmJvHylk78HHFWuruFFVePlit9rZWGA/FbZfTEmNRneGJtha + user:$2y$05$L86zqQDfH5y445dcMlwu6uHv.oXFgT6AiJCwpv3ehr7idc0rI3S2G + # Authentication string for Kubernetes probes, which is needed when `htpasswd` + # authentication is enabled, but the anonymous access policy is not. + # It contains a `user:password` string encoded in base64. The example value is + # from running `echo -n "foo:var" | base64` + # authHeader: "Zm9vOmJhcg==" + + # If persistence is 'true' the service uses a persistentVolumeClaim to mount a + # volume for zot on '/var/lib/registry'; by default the pvc used is named + # '$CHART_RELEASE-pvc', but the name can be changed below + persistence: false + # PVC data, only used if persistence is 'true' + pvc: + # Make the chart create the PVC, this option is used with storageClasses that + # can create volumes dynamically, if that is not the case is better to do it + # manually and set create to false + create: false + # Name of the PVC to use or create if persistence is enabled, if not set the + # value '$CHART_RELEASE-pvc' is used + name: null + # Volume access mode, if using more than one replica we need + accessMode: "ReadWriteOnce" + # Size of the volume requested + storage: 8Gi + # Name of the storage class to use if it is different than the default one + storageClassName: null + # List of environment variables to set on the container + env: + # - name: "TEST" + # value: "ME" + # - name: SECRET_NAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username + + # Extra Volume Mounts + extraVolumeMounts: [] + # - name: data + # mountPath: /var/lib/registry + + # Extra Volumes + extraVolumes: [] + # - name: data + # emptyDir: {} + + # Deployment strategy type + strategy: + type: RollingUpdate + # rollingUpdate: + # maxUnavailable: 25% + + podAnnotations: {} From 3f2ac615f0edf5769b21522a1d41a3a64fda63b2 Mon Sep 17 00:00:00 2001 From: Tyler Gillson Date: Tue, 4 Jun 2024 09:37:06 -0600 Subject: [PATCH 17/22] chore: add coredns chart ref --- packs/k8gb-0.12.2/values.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packs/k8gb-0.12.2/values.yaml b/packs/k8gb-0.12.2/values.yaml index e24ca1fa..2a561d28 100644 --- a/packs/k8gb-0.12.2/values.yaml +++ b/packs/k8gb-0.12.2/values.yaml @@ -7,6 +7,11 @@ pack: - image: otel/opentelemetry-collector:0.57.2 - image: jaegertracing/all-in-one:1.37.0 + charts: + - repository: https://absaoss.github.io/coredns-helm + name: coredns + version: 1.15.3 + namespace: "k8gb" charts: From b377a0a04cd0b383d0c130ba64c92f5dd6b77c13 Mon Sep 17 00:00:00 2001 From: Pedro Oliveira <22790804+JPedro2@users.noreply.github.com> Date: Sun, 16 Jun 2024 08:59:51 +0100 Subject: [PATCH 18/22] fix version typo/mismatch 0.4.0 to 0.40.0 (#83) Co-authored-by: Vishwanath S --- packs/strimzi-kafka-operator-0.40.0/pack.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packs/strimzi-kafka-operator-0.40.0/pack.json b/packs/strimzi-kafka-operator-0.40.0/pack.json index 778b66f9..9fe9f0cb 100644 --- a/packs/strimzi-kafka-operator-0.40.0/pack.json +++ b/packs/strimzi-kafka-operator-0.40.0/pack.json @@ -14,5 +14,5 @@ "displayName": "Strimzi Kafka", "layer":"addon", "name": "strimzi-kafka", - "version": "0.4.0" + "version": "0.40.0" } \ No newline at end of file From 7139111121d926f55a752aabb6fc23101a7c1e0a Mon Sep 17 00:00:00 2001 From: Justin Barksdale Date: Sun, 16 Jun 2024 14:16:05 -0600 Subject: [PATCH 19/22] Updated files with image regerence --- .../charts/crossplane-1.16.0.tgz | Bin 13656 -> 0 bytes packs/crossplane-1.16/schema.yaml | 0 packs/crossplane-1.16/values.yaml | 3 +++ 3 files changed, 3 insertions(+) delete mode 100644 packs/crossplane-1.16/charts/crossplane-1.16.0.tgz delete mode 100644 packs/crossplane-1.16/schema.yaml diff --git a/packs/crossplane-1.16/charts/crossplane-1.16.0.tgz b/packs/crossplane-1.16/charts/crossplane-1.16.0.tgz deleted file mode 100644 index d0ff023a54ddec3d21e4820f64f66d99bd66879e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13656 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 diff --git a/packs/crossplane-1.16/schema.yaml b/packs/crossplane-1.16/schema.yaml deleted file mode 100644 index e69de29b..00000000 diff --git a/packs/crossplane-1.16/values.yaml b/packs/crossplane-1.16/values.yaml index 2f34c284..170e9412 100644 --- a/packs/crossplane-1.16/values.yaml +++ b/packs/crossplane-1.16/values.yaml @@ -2,6 +2,9 @@ pack: #The namespace (on the target cluster) to install this chart #When not found, a new namespace will be created namespace: "crossplane-system" + content: + - image: xpkg.upbound.io/crossplane/crossplane:v1.16.0 + charts: crossplane: From f2b4ffb9c3546e4ff907da4f856ad7883dc535b2 Mon Sep 17 00:00:00 2001 From: Justin Barksdale Date: Sun, 16 Jun 2024 14:19:03 -0600 Subject: [PATCH 20/22] Updated file references --- .../charts/crossplane-1.16.0.tgz | Bin 0 -> 13656 bytes packs/crossplane-1.16/charts/values.yaml | 186 ------------------ packs/crossplane-1.7.0/values.yaml | 2 + 3 files changed, 2 insertions(+), 186 deletions(-) create mode 100644 packs/crossplane-1.16/charts/crossplane-1.16.0.tgz delete mode 100644 packs/crossplane-1.16/charts/values.yaml diff --git a/packs/crossplane-1.16/charts/crossplane-1.16.0.tgz b/packs/crossplane-1.16/charts/crossplane-1.16.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..d0ff023a54ddec3d21e4820f64f66d99bd66879e GIT binary patch literal 13656 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 literal 0 HcmV?d00001 diff --git a/packs/crossplane-1.16/charts/values.yaml b/packs/crossplane-1.16/charts/values.yaml deleted file mode 100644 index 6a319f21..00000000 --- a/packs/crossplane-1.16/charts/values.yaml +++ /dev/null @@ -1,186 +0,0 @@ -# helm-docs renders these comments into markdown. Use markdown formatting where -# appropiate. -# -# -- The number of Crossplane pod `replicas` to deploy. -replicas: 1 - -# -- The deployment strategy for the Crossplane and RBAC Manager pods. -deploymentStrategy: RollingUpdate - -image: - # -- Repository for the Crossplane pod image. - repository: xpkg.upbound.io/crossplane/crossplane - # -- The Crossplane image tag. Defaults to the value of `appVersion` in `Chart.yaml`. - tag: "" - # -- The image pull policy used for Crossplane and RBAC Manager pods. - pullPolicy: IfNotPresent - -# -- Add `nodeSelectors` to the Crossplane pod deployment. -nodeSelector: {} -# -- Add `tolerations` to the Crossplane pod deployment. -tolerations: [] -# -- Add `affinities` to the Crossplane pod deployment. -affinity: {} - -# -- Enable `hostNetwork` for the Crossplane deployment. Caution: enabling `hostNetwork` grants the Crossplane Pod access to the host network namespace. Consider setting `dnsPolicy` to `ClusterFirstWithHostNet`. -hostNetwork: false - -# -- Specify the `dnsPolicy` to be used by the Crossplane pod. -dnsPolicy: "" - -# -- Add custom `labels` to the Crossplane pod deployment. -customLabels: {} - -# -- Add custom `annotations` to the Crossplane pod deployment. -customAnnotations: {} - -serviceAccount: - # -- Add custom `annotations` to the Crossplane ServiceAccount. - customAnnotations: {} - -# -- Enable [leader election](https://docs.crossplane.io/latest/concepts/pods/#leader-election) for the Crossplane pod. -leaderElection: true -# -- Add custom arguments to the Crossplane pod. -args: [] - -provider: - # -- A list of Provider packages to install. - packages: [] - -configuration: - # -- A list of Configuration packages to install. - packages: [] - -function: - # -- A list of Function packages to install - packages: [] - -# -- The imagePullSecret names to add to the Crossplane ServiceAccount. -imagePullSecrets: [] - -registryCaBundleConfig: - # -- The ConfigMap name containing a custom CA bundle to enable fetching packages from registries with unknown or untrusted certificates. - name: "" - # -- The ConfigMap key containing a custom CA bundle to enable fetching packages from registries with unknown or untrusted certificates. - key: "" - -service: - # -- Configure annotations on the service object. Only enabled when webhooks.enabled = true - customAnnotations: {} - -webhooks: - # -- Enable webhooks for Crossplane and installed Provider packages. - enabled: true - -rbacManager: - # -- Deploy the RBAC Manager pod and its required roles. - deploy: true - # -- Don't install aggregated Crossplane ClusterRoles. - skipAggregatedClusterRoles: false - # -- The number of RBAC Manager pod `replicas` to deploy. - replicas: 1 - # -- Enable [leader election](https://docs.crossplane.io/latest/concepts/pods/#leader-election) for the RBAC Manager pod. - leaderElection: true - # -- Add custom arguments to the RBAC Manager pod. - args: [] - # -- Add `nodeSelectors` to the RBAC Manager pod deployment. - nodeSelector: {} - # -- Add `tolerations` to the RBAC Manager pod deployment. - tolerations: [] - # -- Add `affinities` to the RBAC Manager pod deployment. - affinity: {} - -# -- The PriorityClass name to apply to the Crossplane and RBAC Manager pods. -priorityClassName: "" - -resourcesCrossplane: - limits: - # -- CPU resource limits for the Crossplane pod. - cpu: 500m - # -- Memory resource limits for the Crossplane pod. - memory: 1024Mi - requests: - # -- CPU resource requests for the Crossplane pod. - cpu: 100m - # -- Memory resource requests for the Crossplane pod. - memory: 256Mi - -securityContextCrossplane: - # -- The user ID used by the Crossplane pod. - runAsUser: 65532 - # -- The group ID used by the Crossplane pod. - runAsGroup: 65532 - # -- Enable `allowPrivilegeEscalation` for the Crossplane pod. - allowPrivilegeEscalation: false - # -- Set the Crossplane pod root file system as read-only. - readOnlyRootFilesystem: true - -packageCache: - # -- Set to `Memory` to hold the package cache in a RAM backed file system. Useful for Crossplane development. - medium: "" - # -- The size limit for the package cache. If medium is `Memory` the `sizeLimit` can't exceed Node memory. - sizeLimit: 20Mi - # -- The name of a PersistentVolumeClaim to use as the package cache. Disables the default package cache `emptyDir` Volume. - pvc: "" - # -- The name of a ConfigMap to use as the package cache. Disables the default package cache `emptyDir` Volume. - configMap: "" - -resourcesRBACManager: - limits: - # -- CPU resource limits for the RBAC Manager pod. - cpu: 100m - # -- Memory resource limits for the RBAC Manager pod. - memory: 512Mi - requests: - # -- CPU resource requests for the RBAC Manager pod. - cpu: 100m - # -- Memory resource requests for the RBAC Manager pod. - memory: 256Mi - -securityContextRBACManager: - # -- The user ID used by the RBAC Manager pod. - runAsUser: 65532 - # -- The group ID used by the RBAC Manager pod. - runAsGroup: 65532 - # -- Enable `allowPrivilegeEscalation` for the RBAC Manager pod. - allowPrivilegeEscalation: false - # -- Set the RBAC Manager pod root file system as read-only. - readOnlyRootFilesystem: true - -metrics: - # -- Enable Prometheus path, port and scrape annotations and expose port 8080 for both the Crossplane and RBAC Manager pods. - enabled: false - -# -- Add custom environmental variables to the Crossplane pod deployment. -# Replaces any `.` in a variable name with `_`. For example, `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`. -extraEnvVarsCrossplane: {} - -# -- Add custom environmental variables to the RBAC Manager pod deployment. -# Replaces any `.` in a variable name with `_`. For example, `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`. -extraEnvVarsRBACManager: {} - -# -- Add a custom `securityContext` to the Crossplane pod. -podSecurityContextCrossplane: {} - -# -- Add a custom `securityContext` to the RBAC Manager pod. -podSecurityContextRBACManager: {} - -# -- Add custom `volumes` to the Crossplane pod. -extraVolumesCrossplane: {} - -# -- Add custom `volumeMounts` to the Crossplane pod. -extraVolumeMountsCrossplane: {} - -# -- To add arbitrary Kubernetes Objects during a Helm Install -extraObjects: [] - # - apiVersion: pkg.crossplane.io/v1alpha1 - # kind: ControllerConfig - # metadata: - # name: aws-config - # annotations: - # eks.amazonaws.com/role-arn: arn:aws:iam::123456789101:role/example - # helm.sh/hook: post-install - # spec: - # podSecurityContext: - # fsGroup: 2000 - diff --git a/packs/crossplane-1.7.0/values.yaml b/packs/crossplane-1.7.0/values.yaml index 8c2d25ca..db518c4a 100644 --- a/packs/crossplane-1.7.0/values.yaml +++ b/packs/crossplane-1.7.0/values.yaml @@ -2,6 +2,8 @@ pack: #The namespace (on the target cluster) to install this chart #When not found, a new namespace will be created namespace: "crossplane" + content: + - image: xpkg.upbound.io/crossplane/crossplane:v1.7.0 charts: crossplane: From ef1cfa33f4bbc6220c5f1166ce86455f8b373bd6 Mon Sep 17 00:00:00 2001 From: Justin Barksdale Date: Sun, 16 Jun 2024 14:24:03 -0600 Subject: [PATCH 21/22] updated images yaml --- packs/crossplane-1.16/values.yaml | 3 ++- packs/crossplane-1.7.0/README.md | 1 + packs/crossplane-1.7.0/values.yaml | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 packs/crossplane-1.7.0/README.md diff --git a/packs/crossplane-1.16/values.yaml b/packs/crossplane-1.16/values.yaml index 170e9412..eb699d62 100644 --- a/packs/crossplane-1.16/values.yaml +++ b/packs/crossplane-1.16/values.yaml @@ -3,7 +3,8 @@ pack: #When not found, a new namespace will be created namespace: "crossplane-system" content: - - image: xpkg.upbound.io/crossplane/crossplane:v1.16.0 + images: + - image: xpkg.upbound.io/crossplane/crossplane:v1.16.0 charts: diff --git a/packs/crossplane-1.7.0/README.md b/packs/crossplane-1.7.0/README.md new file mode 100644 index 00000000..e71fe631 --- /dev/null +++ b/packs/crossplane-1.7.0/README.md @@ -0,0 +1 @@ +Crossplane Deprecated \ No newline at end of file diff --git a/packs/crossplane-1.7.0/values.yaml b/packs/crossplane-1.7.0/values.yaml index db518c4a..fec8c88b 100644 --- a/packs/crossplane-1.7.0/values.yaml +++ b/packs/crossplane-1.7.0/values.yaml @@ -3,7 +3,8 @@ pack: #When not found, a new namespace will be created namespace: "crossplane" content: - - image: xpkg.upbound.io/crossplane/crossplane:v1.7.0 + images: + - image: xpkg.upbound.io/crossplane/crossplane:v1.7.0 charts: crossplane: From cbee6e5df2237839df15d23af592548b693917e2 Mon Sep 17 00:00:00 2001 From: Justin Barksdale Date: Mon, 29 Jul 2024 06:39:19 -0400 Subject: [PATCH 22/22] Added default preset --- packs/crossplane-1.16/presets.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packs/crossplane-1.16/presets.yaml b/packs/crossplane-1.16/presets.yaml index 35186399..b35fc47b 100644 --- a/packs/crossplane-1.16/presets.yaml +++ b/packs/crossplane-1.16/presets.yaml @@ -8,4 +8,14 @@ presets: crossplane: provider: packages: - - "xpkg.upbound.io/crossplane-contrib/provider-palette:v0.19.2" \ No newline at end of file + - "xpkg.upbound.io/crossplane-contrib/provider-palette:v0.19.2" + - name: "no-provider" + displayName: "Remove Preset Providers" + group: "Provider" + remove: | + charts: + crossplane: + provider: + packages: + - "xpkg.upbound.io/crossplane-contrib/provider-palette:v0.19.2" + add: [] \ No newline at end of file

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 + account: + username: + password: + accessKey: + +agentServiceAccount: appdynamics-auto-instrumentation-agent + +instrumentationConfig: + enabled: false + containerAppCorrelationMethod: proxy +``` +### Install cluster agent or machine agent using helm chart +```bash +helm install auto-instrumentation-agent appdynamics-charts/auto-instrumentation-agent -f .yaml --namespace appdynamics +``` + +### Note: +auto instrumentation agent installation is independent of otel collector. \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/_helper.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/_helper.tpl new file mode 100644 index 00000000..ea40b4ed --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/_helper.tpl @@ -0,0 +1,3 @@ +{{- define "appdynamics-auto-instrumentation-agent.sensitiveDataController" -}} +{{ (get . "data") | trim | b64enc | required (get . "message") }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/auto-instrumentation-agent.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/auto-instrumentation-agent.yaml new file mode 100644 index 00000000..0022a3a2 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/auto-instrumentation-agent.yaml @@ -0,0 +1,174 @@ +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: AutoInstrumentationAgent +metadata: + name: {{ (cat (regexReplaceAll "([^a-zA-Z0-9-.]+)" (lower (.Values.autoInstrumentationAgent.agentName | default (cat .Release.Name "-" "ai-agent" | nospace))) "-") "-" .Release.Namespace | nospace) | trunc 63 }} + namespace: {{ .Release.Namespace }} +spec: + agentName: {{ cat .Release.Name "-" "ai-agent" "-" .Release.Namespace }} + controllerUrl: {{ required "AppDynamics controller URL is required!" .Values.controllerInfo.url }} + account: {{ required "AppDynamics controller account is required!" .Values.controllerInfo.account }} + image: {{ .Values.imageInfo.agentImage }}:{{ .Values.imageInfo.agentTag }} + serviceAccountName: {{ .Values.agentServiceAccount }} + + {{ if .Values.controllerInfo.customSSLCert -}} + # Custom SSL config + customSSLSecret: auto-instrumentation-agent-ssl-cert + {{- end }} + + {{ with .Values.controllerInfo -}} + {{ if .proxyUrl -}} + # Proxy config + proxyUrl: {{ .proxyUrl }} + {{ if .authenticateProxy -}} + proxyUser: {{ required "Proxy user is required to authenticate proxy!" .proxyUser }} + {{- end }} + {{- end }} + {{- end }} + + # Log specific properties + {{ with .Values.logProperties -}} + logFileSizeMb: {{ .logFileSizeMb }} + logFileBackups: {{ .logFileBackups }} + logLevel: {{ .logLevel }} + {{- end }} + + + {{ if .Values.imageInfo.imagePullPolicy -}} + # Image pull policy + imagePullPolicy: {{ .Values.imageInfo.imagePullPolicy }} + {{- end }} + + {{ if .Values.imageInfo.imagePullSecret -}} + # Image pull secret + imagePullSecret: {{ .Values.imageInfo.imagePullSecret }} + {{- end }} + + #labels + labels: + {{- toYaml .Values.autoInstrumentationAgent.labels | nindent 4 }} + + # Node selector + nodeSelector: + {{- toYaml .Values.autoInstrumentationAgent.nodeSelector | nindent 4 }} + + # Tolerations + tolerations: + {{- toYaml .Values.autoInstrumentationAgent.tolerations | nindent 4 }} + + # Resources + resources: + {{- toYaml .Values.autoInstrumentationAgent.resources | nindent 4 }} + + {{ with .Values.instrumentationConfig -}} + # Instrumentation config + {{ if .defaultAppName -}} + defaultAppName: {{ .defaultAppName }} + {{- end }} + {{ if .defaultEnv -}} + defaultEnv: {{ .defaultEnv }} + {{- end }} + {{ if .defaultInstrumentationLabelMatch -}} + defaultInstrumentationLabelMatch: + {{- toYaml .defaultInstrumentationLabelMatch | nindent 4 }} + {{- end }} + {{ if .defaultInstrumentMatchString -}} + defaultInstrumentMatchString: {{ .defaultInstrumentMatchString }} + {{- end }} + {{ if .defaultCustomConfig -}} + defaultCustomConfig: {{ .defaultCustomConfig }} + {{- end }} + {{ if .appNameStrategy -}} + appNameStrategy: {{ .appNameStrategy }} + {{- end }} + {{ if .tierNameStrategy -}} + tierNameStrategy: {{ .tierNameStrategy }} + {{- end }} + {{ if .appNameLabel -}} + appNameLabel: {{ .appNameLabel }} + {{- end }} + {{ if .tierNameLabel -}} + tierNameLabel: {{ .tierNameLabel }} + {{- end }} + {{ if .nodeName -}} + nodeName: {{ .nodeName }} + {{- end }} + {{ if .imageInfo -}} + imageInfo: + {{- toYaml .imageInfo | nindent 4}} + {{- end }} + {{ if .instrumentationMethod -}} + instrumentationMethod: {{ .instrumentationMethod }} + {{- end }} + {{ if .resourcesToInstrument -}} + resourcesToInstrument: + {{- toYaml .resourcesToInstrument | nindent 4 }} + {{- end }} + {{ if .instrumentationRules -}} + instrumentationRules: + {{- toYaml .instrumentationRules | nindent 4 }} + {{- end }} + {{ if .nsToInstrumentRegex -}} + nsToInstrumentRegex: {{ .nsToInstrumentRegex }} + {{- end }} + {{ if .netvizInfo -}} + netvizInfo: + {{- toYaml .netvizInfo | nindent 4 }} + {{- end }} + {{ if .runAsUser -}} + runAsUser: {{ .runAsUser }} + {{- end }} + {{ if .runAsGroup -}} + runAsGroup: {{ .runAsGroup }} + {{- end }} + {{ if .runAsNonRoot -}} + runAsNonRoot: {{ .runAsNonRoot }} + {{- end }} + {{ if .readOnlyRootFilesystem -}} + readOnlyRootFilesystem: {{ .readOnlyRootFilesystem }} + {{- end }} + {{ if .allowPrivilegeEscalation -}} + allowPrivilegeEscalation: {{ .allowPrivilegeEscalation }} + {{- end }} + {{ if .capabilities -}} + capabilities: {{ .capabilities }} + {{- end }} + {{ if .seccompProfile -}} + seccompProfile: {{ .seccompProfile }} + {{- end }} + {{ if .windowsOptions -}} + windowsOptions: {{ .windowsOptions }} + {{- end }} + {{ if .seLinuxOptions -}} + seLinuxOptions: {{ .seLinuxOptions }} + {{- end }} + {{ if .procMount -}} + procMount: {{ .procMount }} + {{- end }} + {{ if .privileged -}} + privileged: {{ .privileged }} + {{- end }} + {{ if .numberOfTaskWorkers -}} + numberOfTaskWorkers: {{ .numberOfTaskWorkers }} + {{- end }} + {{ if .defaultAnalyticsHost -}} + defaultAnalyticsHost: {{ .defaultAnalyticsHost }} + {{- end }} + {{ if .defaultAnalyticsPort -}} + defaultAnalyticsPort: {{ .defaultAnalyticsPort }} + {{- end }} + {{ if .defaultAnalyticsSslEnabled -}} + defaultAnalyticsSslEnabled: {{ .defaultAnalyticsSslEnabled }} + {{- end }} + {{ if .enableInstallationReport -}} + enableInstallationReport: {{ .enableInstallationReport }} + {{ end -}} + {{ if .enableForceReInstrumentation -}} + enableForceReInstrumentation: {{ .enableForceReInstrumentation }} + {{ end -}} + {{if .containerAppCorrelationMethod -}} + containerAppCorrelationMethod: {{ .containerAppCorrelationMethod }} + {{ end -}} + {{if .metadataServerPort -}} + metadataServerPort: {{ .metadataServerPort }} + {{ end -}} + {{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/cr-agent-instrumentation.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/cr-agent-instrumentation.yaml new file mode 100644 index 00000000..5391eabb --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/cr-agent-instrumentation.yaml @@ -0,0 +1,63 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: appdynamics-auto-instrumentation-agent-{{.Release.Name}} +rules: +- apiGroups: + - "" + resources: + - pods + - pods/exec + - secrets + - configmaps + verbs: + - create + - update + - delete +- apiGroups: + - apps + resources: + - daemonsets + - statefulsets + - deployments + - replicasets + verbs: + - update +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - update + - list +{{ if .Capabilities.APIVersions.Has "apps.openshift.io/v1/DeploymentConfig" -}} +- apiGroups: + - apps.openshift.io + resources: + - deploymentconfigs + verbs: + - update +{{- end }} +{{ with .containerAppCorrelationMethod }} +{{ if eq . "kubeapi" }} +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - create + - delete +- apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + - rolebindings + verbs: + - get + - create + - update + - delete +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/crb-agent-instrumentation.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/crb-agent-instrumentation.yaml new file mode 100644 index 00000000..a2468f7d --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/crb-agent-instrumentation.yaml @@ -0,0 +1,14 @@ +{{ $agentSA := .Values.agentServiceAccount }} +{{ $namespace := .Release.Namespace }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: appdynamics-auto-instrumentation-agent-{{.Release.Name}} +subjects: + kind: ServiceAccount + name: {{ $agentSA }} + namespace: {{ $namespace }} +roleRef: + kind: ClusterRole + name: appdynamics-auto-instrumentation-agent-instrumentation-{{.Release.Name}} + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/sa-agent.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/sa-agent.yaml new file mode 100644 index 00000000..64f85107 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/sa-agent.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.agentServiceAccount }} + namespace: {{ .Release.Namespace }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-auto-instrumentation-agent.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-auto-instrumentation-agent.yaml new file mode 100644 index 00000000..38531ca6 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-auto-instrumentation-agent.yaml @@ -0,0 +1,23 @@ +{{ $secret := (lookup "v1" "Secret" .Release.Namespace "auto-instrumentation-agent-secret") }} +{{ $annotations := dict "temp" "temp" }} +{{ if $secret }} + {{ $annotations = $secret.metadata.annotations }} +{{ end }} +{{ if or (not ($secret)) (get $annotations "appdynamics.helm.charts/created-by") }} +{{ $namespace := .Release.Namespace }} +apiVersion: v1 +kind: Secret +metadata: + name: auto-instrumentation-agent-secret + namespace: {{ $namespace }} + annotations: + appdynamics.helm.charts/created-by: auto-instrumentation-agent-helm-chart +type: Opaque +data: + {{ with .Values.controllerInfo -}} + controller-key: {{ include "appdynamics-auto-instrumentation-agent.sensitiveDataController" (dict "data" .accessKey "message" "AppDynamics controller access key is required!") }} + {{- end -}} + {{ with .Values.controllerInfo }} + api-user: {{ cat (.username | trim | required "AppDynamics controller username is required!") "@" (.account | trim | required "AppDynamics controller account is required!") ":" (.password | trim | required "Appdynamics controller password is required!") | nospace | b64enc -}} + {{- end -}} +{{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-custom-ssl.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-custom-ssl.yaml new file mode 100644 index 00000000..a02204b2 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-custom-ssl.yaml @@ -0,0 +1,22 @@ +{{ $secret := (lookup "v1" "Secret" .Release.Namespace "auto-instrumentation-agent-ssl-cert") }} +{{ $annotations := dict "temp" "temp" }} +{{ if $secret }} + {{ $annotations = $secret.metadata.annotations }} +{{ end }} +{{ if or (not ($secret)) (get $annotations "appdynamics.helm.charts/created-by") }} +{{ $namespace := .Release.Namespace }} +{{ with .Values -}} +{{ if .controllerInfo.customSSLCert -}} +apiVersion: v1 +kind: Secret +metadata: + name: auto-instrumentation-ssl-cert + namespace: {{ $namespace }} + annotations: + appdynamics.helm.charts/created-by: auto-instrumentation-agent-helm-chart +type: Opaque +data: + "custom-ssl.pem": {{ .controllerInfo.customSSLCert }} +{{ end -}} +{{ end -}} +{{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-proxy-secret.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-proxy-secret.yaml new file mode 100644 index 00000000..5d1e196e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-proxy-secret.yaml @@ -0,0 +1,25 @@ +{{ $secret := (lookup "v1" "Secret" .Release.Namespace "auto-instrumentation-proxy-secret") }} +{{ $annotations := dict "temp" "temp" }} +{{ if $secret }} + {{ $annotations = $secret.metadata.annotations }} +{{ end }} +{{ if or (not ($secret)) (get $annotations "appdynamics.helm.charts/created-by") }} +{{ $namespace := .Release.Namespace }} +{{ with .Values -}} +{{ if .controllerInfo.authenticateProxy -}} +{{ if not .controllerInfo.proxyUrl -}} +{{ fail "Proxy url is requried to authenticate proxy!" -}} +{{ end -}} +apiVersion: v1 +kind: Secret +metadata: + name: auto-instrumentation-proxy-secret + namespace: {{ $namespace }} + annotations: + appdynamics.helm.charts/created-by: auto-instrumentation-helm-chart +type: Opaque +data: + proxy-password: {{ include "sensitiveData" (dict "data" .controllerInfo.proxyPassword "message" "Proxy password is required!") }} +{{ end -}} +{{ end -}} +{{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/values.yaml new file mode 100644 index 00000000..4ff50709 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/values.yaml @@ -0,0 +1,48 @@ +# Docker images +imageInfo: + agentImage: docker.io/appdynamics/auto-instrumentation-agent + agentTag: 24.4.0 + imagePullPolicy: Always + imagePullSecret: null + +#Auto Instrumentation Agent +autoInstrumentationAgent: + agentName: null + labels: {} + nodeSelector: {} + tolerations: [] + resources: + limits: + cpu: "100m" + memory: "300Mi" + requests: + cpu: "50m" + memory: "150Mi" +# AppDynamics controller info (VALUES TO BE PROVIDED BY THE USER) +controllerInfo: + url: "" + account: "" + username: "" + password: "" + accessKey: "" + customSSLCert: null + + # Proxy config + authenticateProxy: false + proxyUrl: null + proxyUser: null + proxyPassword: null + +# RBAC config +createServiceAccount: true +agentServiceAccount: appdynamics-auto-instrumentation-agent + +# Instrumentation config +instrumentationConfig: + enabled: false + containerAppCorrelationMethod: proxy + +logProperties: + logFileSizeMb: 5 + logFileBackups: 3 + logLevel: INFO \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/.helmignore b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/Chart.yaml new file mode 100644 index 00000000..79af63bd --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v2 +appVersion: 24.4.0 +description: Helm Chart to deploy dbcollector as a deployment and corresponding dbconfigs. +home: https://appdynamics.com +icon: https://raw.githubusercontent.com/CiscoDevNet/appdynamics-charts/master/logo.png +keywords: +- appdynamics +- database +- dbcollector +- dbconfig +- kubernetes +- monitoring +- pod +- deployment +maintainers: +- email: support@appdynamics.com + name: AppDynamics +name: appdynamics-cloud-db-collector +version: 1.9.0 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/_helper.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/_helper.tpl new file mode 100644 index 00000000..d015dc6a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/_helper.tpl @@ -0,0 +1,36 @@ +{{- define "appdynamics-cloud-db-collector.getClusterID" }} +{{ if .Values.global.smartAgentInstall -}} +# If installation is via the smartagent, use the special purpose value to set what is being used by the smartagent. +clusterID: {{ "AGENT_PLATFORM_ID_VALUE" }} +{{ else }} +{{- if (lookup "v1" "Namespace" "" "kube-system").metadata }} +clusterID: {{ required "Could not fetch kube-system uid to populate clusterID! " (lookup "v1" "Namespace" "" "kube-system").metadata.uid }} +{{- else -}} +clusterID: {{ .Values.global.clusterId | required "clusterId needs to be specified when kube-system metadata is not accessible!" }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "appdynamics-cloud-db-collector.podConfigs" }} + image: {{ .image }} + imagePullPolicy: {{ .imagePullPolicy }} + resources: + {{- toYaml .resources | nindent 4 }} + labels: + {{- toYaml .labels | nindent 4 }} + annotations: + {{- toYaml .annotations | nindent 4 }} + nodeSelector: + {{- toYaml .nodeSelector | nindent 4 }} + imagePullSecrets: + {{- toYaml .imagePullSecrets | nindent 4 }} + affinity: + {{- toYaml .affinity | nindent 4 }} + tolerations: + {{- toYaml .tolerations | nindent 4 }} + securityContext: + {{- toYaml .securityContext | nindent 4 }} + {{ if .priorityClassName -}} + priorityClassName: {{ .priorityClassName }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbCollector.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbCollector.yaml new file mode 100644 index 00000000..a80ed20a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbCollector.yaml @@ -0,0 +1,56 @@ +{{ if .Values.install.dbCollector -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +# Kind will match the Kind section in generated CRD at Operator +kind: DbCollector +# Release is picked up from the command +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-db-collector" | trunc 63 }} + namespace: {{ .Release.Namespace }} +spec: + # spec for dbCollector here + {{- $mergedPodConfig := .Values.dbCollectorPod }} + {{- template "appdynamics-cloud-db-collector.podConfigs" $mergedPodConfig }} + {{ with .Values.appdCloudAuth -}} + # CIS credentials + clientId: {{ .clientId }} + # either clientSecret will be present + {{ if .clientSecret -}} + clientSecret: {{ .clientSecret }} + {{ else }} + # if clientSecret is not present then clientSecretKeyRef is expected + clientSecretVarSource: {{- toYaml .clientSecretEnvVar.valueFrom | nindent 4 }} + {{- end }} + endpoint: {{ .endpoint }} + tokenUrl: {{ .tokenUrl }} + + {{- end }} + + {{ with .Values.dbCollectorConfig -}} + os: "linux" + arch: "amd64" + # Profiling flag and port + pprofEnable: {{ .pprof.enabled }} + {{ if .pprof.enabled -}} + pprofPort: {{ .pprof.port }} + {{- end }} + # Prometheus flag and port + metricEnable: {{ .metric.enabled }} + {{ if .metric.enabled -}} + metricPort: {{ .metric.port }} + {{- end }} + # Log level + logLevel : {{ .logLevel }} + {{- end }} + {{ if ne .Values.dbCollectorPod.image "appdynamics/appdynamics-cloud-db-collector:23.2.0-539"}} + # Mount path for generated config + configMountPath: /opt/appdynamics/appddbcol/conf/generated + {{ end }} + # To control the Agent Management client start by db collector + agentManagementEnabled: {{ .Values.install.agentManagementEnabled }} + # Name of the running instance of db collector. Optional, should be provided by user to distinguish multiple db collector instance on same platform. + collectorInstanceName: {{.Values.dbCollectorName}} + # Name of the Agent should be fixed to release name. Not modified by end user. + collectorName: {{ .Release.Name }} + clusterName: {{ .Values.global.clusterName }} + {{- include "appdynamics-cloud-db-collector.getClusterID" . | nindent 2 }} +{{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbConfig.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbConfig.yaml new file mode 100644 index 00000000..cd781c89 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbConfig.yaml @@ -0,0 +1,61 @@ +{{ if .Values.install.dbMonitoringConfigs -}} +# loop over available dbconfigs to create multiple CRs +{{- range .Values.dbMonitoringConfigs }} +# convert given configname to lower case +{{ $configResName := lower .configName }} +# default dbPasswordSecretName +{{- $dbPasswordSecretName := printf "%s-%s-%s" $.Release.Name $configResName "db-password"}} +--- +apiVersion: cluster.appdynamics.com/v1alpha1 +# Kind will match the Kind section in generated CRD at Operator +kind: DbConfig +# Release is picked up from the command +metadata: + name: {{ printf "%s-%s" $.Release.Name $configResName | trunc 255 }} + namespace: {{ $.Release.Namespace }} +spec: + # spec for dbConfigs here + dbType: {{ .dbType }} + configName: {{ .configName }} + # if collector name is specified, otherwise default to collector deployed via current release + {{ if not .dbCollector }} + dbCollector: + name: {{ printf "%s-%s" $.Release.Name "appdynamics-db-collector" | trunc 63 }} + namespace: {{ $.Release.Namespace }} + {{ else }} + dbCollector: + name: {{ .dbCollector.name }} + namespace: {{ .dbCollector.namespace }} + {{ end }} + hostname: {{ .hostname }} + hostport: {{ .hostport }} + username: {{ .username }} + # if Secret Name containing the password is given + {{ if .passwordSecretName }} + passwordSecretName: {{ .passwordSecretName }} + # otherwise use the created secret + {{ else }} + passwordSecretName: {{ $dbPasswordSecretName}} + {{ end }} + + # database : optional field + {{ if .database -}} + database: {{ .database }} + {{ end -}} + # environment : optional field + {{ if .environment -}} + environment: + platform: {{ .environment.platform }} + {{ end }} + # tlsconfig : optional field + {{ if .tlsConfig -}} + tlsConfig: + # hostnameincertificate : optional field + {{ if .tlsConfig.hostNameInCertificate -}} + hostNameInCertificate: {{ .tlsConfig.hostNameInCertificate }} + {{- end }} + certSecretName: {{ .tlsConfig.certSecretName }} + + {{ end }} +{{- end }} +{{ end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbConfigDbPasswordSecrets.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbConfigDbPasswordSecrets.yaml new file mode 100644 index 00000000..4124c03e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbConfigDbPasswordSecrets.yaml @@ -0,0 +1,24 @@ +# This manifest creates a default secret for the dbconfig whose secret is passed as a string + +{{ if .Values.install.dbMonitoringConfigs -}} +# loop over available dbconfigs to create multiple CRs +{{- range .Values.dbMonitoringConfigs }} +# convert given configname to lower case +{{ $configResName := lower .configName }} +# default dbSecretName +{{- $dbPasswordSecretName := printf "%s-%s-%s" $.Release.Name $configResName "db-password"}} + +# secret to be created if db passwordSecretName is not provided( provided as a string ) +{{ if not .passwordSecretName }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $dbPasswordSecretName }} + namespace: {{ $.Release.Namespace }} +type: Opaque +stringData: + password: {{ .password }} +{{ end }} +{{- end }} +{{ end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/rbac/dbcollector_openshift_scc.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/rbac/dbcollector_openshift_scc.yaml new file mode 100644 index 00000000..02135354 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/rbac/dbcollector_openshift_scc.yaml @@ -0,0 +1,24 @@ +{{ if or .Values.install.dbCollector .Values.install.dbMonitoringConfigs -}} +{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1/SecurityContextConstraints" -}} +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + annotations: + kubernetes.io/description: 'dbcollector-privileged-scc is a custom SCC for AppDynamics Cloud Database Collector' + name: dbcollector-privileged-scc + namespace: {{ .Release.Namespace }} +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegedContainer: false +readOnlyRootFilesystem: false +runAsUser: + type: RunAsAny +seLinuxContext: + type: MustRunAs +users: + - system:serviceaccount:{{ .Release.Namespace }}:{{ .Values.dbcollectorServiceAccount }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/rbac/dbcollector_service_account.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/rbac/dbcollector_service_account.yaml new file mode 100644 index 00000000..bc09923e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/rbac/dbcollector_service_account.yaml @@ -0,0 +1,7 @@ +{{ if or .Values.install.dbCollector .Values.install.dbMonitoringConfigs -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.dbcollectorServiceAccount }} + namespace: {{ .Release.Namespace }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/values.schema.json b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/values.schema.json new file mode 100644 index 00000000..e0a21011 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/values.schema.json @@ -0,0 +1,415 @@ +{ + "$schema": "http://json-schema.org/schema#", + "$ref": "#/definitions/Core", + "definitions": { + "Core": { + "type": "object", + "additionalProperties": true, + "properties": { + "dbCollectorName": { + "type": "string" + }, + "appdCloudAuth": { + "$ref": "#/definitions/AppdCloudAuth" + }, + "install": { + "$ref": "#/definitions/Install" + }, + "dbCollectorConfig": { + "$ref": "#/definitions/DBCollectorConfig" + }, + "dbMonitoringConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/DBMonitoringConfig" + } + }, + "dbCollectorPod": { + "$ref": "#/definitions/DBCollectorPod" + } + }, + "required": [ + "install" + ], + "title": "Core" + }, + "AppdCloudAuth": { + "type": "object", + "additionalProperties": false, + "properties": { + "clientId": { + "type": "string" + }, + "clientSecret": { + "type": "string" + }, + "clientSecretEnvVar": { + "$ref": "#/definitions/ClientSecretEnvVar" + }, + "endpoint": { + "type": "string" + }, + "tokenUrl": { + "type": "string" + } + }, + "anyOf": [ + { "required": + [ "clientSecret" ] + }, + { "required": + [ "clientSecretEnvVar" ] + } + ], + "required": [ + "clientId", + "endpoint", + "tokenUrl" + ], + "title": "AppdCloudAuth" + }, + "ClientSecretEnvVar": { + "type": "object", + "additionalProperties": false, + "properties": { + "valueFrom": { + "$ref": "#/definitions/ValueFrom" + } + }, + "required": [ + "valueFrom" + ], + "title": "ClientSecretEnvVar" + }, + "ValueFrom": { + "type": "object", + "additionalProperties": false, + "properties": { + "secretKeyRef": { + "$ref": "#/definitions/SecretKeyRef" + } + }, + "required": [ + "secretKeyRef" + ], + "title": "ValueFrom" + }, + "SecretKeyRef": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "key": { + "type": "string" + } + }, + "required": [ + "key", + "name" + ], + "title": "SecretKeyRef" + }, + "DBCollectorConfig": { + "type": "object", + "additionalProperties": false, + "properties": { + "logLevel": { + "type" : "string", + "enum": ["off", "error", "warn","info","debug","all"] + }, + "pprof": { + "$ref": "#/definitions/Pprof" + }, + "metric": { + "$ref": "#/definitions/metric" + } + }, + "required": [ + "logLevel" + ], + "title": "DBCollectorConfig" + }, + "Pprof": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "port": { + "type": ["integer","null"] + } + }, + "required": [ + "enabled" + ], + "title": "Pprof" + }, + "metric": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "port": { + "type": ["integer","null"] + } + }, + "required": [ + "enabled" + ], + "title": "metric" + }, + "DBCollectorPod": { + "type": "object", + "additionalProperties": false, + "properties": { + "image": { + "type": "string" + }, + "imagePullPolicy": { + "type": "string" + }, + "priorityClassName": { + "type": ["null","string"] + }, + "resources": { + "$ref": "#/definitions/Resources" + }, + "labels": { + "$ref": "#/definitions/Affinity" + }, + "annotations": { + "$ref": "#/definitions/Affinity" + }, + "nodeSelector": { + "$ref": "#/definitions/Affinity" + }, + "imagePullSecrets": { + "type": "array", + "items": { + "type": "object" + } + }, + "affinity": { + "$ref": "#/definitions/Affinity" + }, + "tolerations": { + "type": "array", + "items": { + "type": "object" + } + }, + "securityContext": { + "$ref": "#/definitions/Affinity" + } + }, + "required": [ + "image", + "imagePullPolicy" + ], + "title": "DBCollectorPod" + }, + "Affinity": { + "type": "object", + "additionalProperties": true, + "title": "Affinity" + }, + "Resources": { + "type": "object", + "additionalProperties": false, + "properties": { + "limits": { + "$ref": "#/definitions/Limits" + }, + "requests": { + "$ref": "#/definitions/Limits" + } + }, + "required": [ + "limits", + "requests" + ], + "title": "Resources" + }, + "Limits": { + "type": "object", + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + }, + "required": [ + "cpu", + "memory" + ], + "title": "Limits" + }, + "DBMonitoringConfig": { + "type": "object", + "additionalProperties": false, + "properties": { + "dbType": { + "type": "string", + "enum": ["sqlserver","mysql","mariadb","aurora-mysql","postgres", "aurora-postgresql"] + }, + "configName": { + "type": "string" + }, + "dbCollector": { + "$ref": "#/definitions/DbCollector" + }, + "hostname": { + "type": "string" + }, + "hostport": { + "type": ["null","integer"] + }, + "username": { + "type": "string" + }, + "password": { + "type": "string" + }, + "passwordSecretName": { + "type": "string" + }, + "database": { + "type": ["null","string"] + }, + "tlsConfig": { + "$ref": "#/definitions/TLSConfig" + }, + "environment": { + "$ref": "#/definitions/Environment" + } + }, + "required": [ + "dbType", + "configName", + "hostname", + "hostport", + "username" + ], + "if": { + "properties": { + "dbType": { "enum": ["mysql", "mariadb","aurora-mysql"]} + } + }, + "then": { + "not": { + "required": ["database"] + } + }, + "else" : { + "if": { + "properties": { + "dbType": { "enum": ["postgres", "aurora-postgresql"] } + } + }, + "then": { + "anyOf": [ + { + "not": { + "required": ["tlsConfig"] + } + }, + { + "properties": { + "tlsConfig": { + "not": { + "required": ["hostNameInCertificate"] + } + } + } + } + ] + } + }, + "oneOf": [ + { + "required" : [ + "password" + ] + }, + { + "required" : [ + "passwordSecretName" + ] + } + ], + "title": "DBMonitoringConfig" + }, + "DbCollector": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + } + }, + "required": [ + "name", + "namespace" + ], + "title": "DbCollector" + }, + "Environment": { + "type": "object", + "additionalProperties": false, + "properties": { + "platform": { + "type": ["null","string"], + "pattern":"^(?i)(azure|aws|self-hosted)$" + } + }, + "title": "Environment" + }, + "TLSConfig": { + "type": "object", + "additionalProperties": false, + "properties": { + "hostNameInCertificate": { + "type": ["null","string"] + }, + "certSecretName": { + "type": "string" + } + }, + "required": [ + "certSecretName" + ], + "title": "TLSConfig" + }, + "Install": { + "type": "object", + "additionalProperties": false, + "properties": { + "dbCollector": { + "type": "boolean" + }, + "dbMonitoringConfigs": { + "type": "boolean" + }, + "agentManagementEnabled" : { + "type": "boolean" + } + }, + "required": [ + "dbCollector", + "dbMonitoringConfigs" + ], + "title": "Install" + } + } +} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/values.yaml new file mode 100644 index 00000000..9c9972d5 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/values.yaml @@ -0,0 +1,78 @@ +appdCloudAuth : +# Example format + clientId: "" + # Either of clientSecret or ClientSecretEnvVar will be present + clientSecret: "" +# clientSecretEnvVar: +# valueFrom: +# secretKeyRef: +# name: "" +# key: "" + endpoint: "" + tokenUrl: "" + +install: + dbCollector: false + dbMonitoringConfigs: false + agentManagementEnabled: true + +# Database Collector Instance Name to uniquely identify multiple instance in same platform +dbCollectorName: "" +dbcollectorServiceAccount: appdynamics-dbcollector + +# dbCollector Configs +dbCollectorConfig: + logLevel: info +# Enables profiling, Not intended for cust use + pprof: + enabled : false + port : 9811 +# Enables Metric for prometheus + metric: + enabled : false + port : 7000 + + +# each Object in the list will create a custom resource of dbconnection type +dbMonitoringConfigs: [] +# Example +# - dbType: "" +# configName: "" +# # Optional collector configuration +# dbCollector: +# name: "" +# namespace: "" +# hostname: "" +# hostport: null +# username: "" +# password: "" +# # database is optional except for azure sql database +# database: "" +# # tlsConfig is optional +# tlsConfig: +# # hostNameInCertificate in tlsConfig is optional +# hostNameInCertificate: "" +# certSecretName: "" +# # environment is optional +# environment: +# platform: null + + +dbCollectorPod: + image: appdynamics/appdynamics-cloud-db-collector:24.2.0-1084 + imagePullPolicy: Always + priorityClassName: null + resources: + limits: + cpu: 500m + memory: 1000Mi + requests: + cpu: 200m + memory: 750Mi + labels: {} + annotations: {} + nodeSelector: {} + imagePullSecrets: [] + affinity: {} + tolerations: [] + securityContext: {} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/.helmignore b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/Chart.yaml new file mode 100644 index 00000000..e7c47fc5 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +appVersion: 24.4.0 +description: Helm Chart to deploy clustermon as a deployment and infra manager, containermon, + servermon, log collector as a daemonset. +home: https://appdynamics.com +icon: https://raw.githubusercontent.com/CiscoDevNet/appdynamics-charts/master/logo.png +keywords: +- appdynamics +- cluster +- kubernetes +- monitoring +- pod +- deployment +maintainers: +- email: support@appdynamics.com + name: AppDynamics +name: appdynamics-cloud-k8s-monitoring +version: 1.21.0 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/_helper.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/_helper.tpl new file mode 100644 index 00000000..d8ca1d35 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/_helper.tpl @@ -0,0 +1,561 @@ +{{- define "appdynamics-cloud-k8s-monitoring.sensitiveData" -}} +{{ (get . "data") | trim | b64enc | required (get . "message") }} +{{- end -}} + +{{- define "appdynamics-cloud-k8s-monitoring.podConfigs" }} + image: {{ .image }} + imagePullPolicy: {{ .imagePullPolicy }} + resources: + {{- toYaml .resources | nindent 4 }} + labels: + {{- toYaml .labels | nindent 4 }} + annotations: + {{- toYaml .annotations | nindent 4 }} + nodeSelector: + {{- toYaml .nodeSelector | nindent 4 }} + imagePullSecrets: + {{- toYaml .imagePullSecrets | nindent 4 }} + affinity: + {{- toYaml .affinity | nindent 4 }} + tolerations: + {{- toYaml .tolerations | nindent 4 }} + securityContext: + {{- toYaml .securityContext | nindent 4 }} + {{ if .priorityClassName -}} + priorityClassName: {{ .priorityClassName }} + {{- end }} +{{- end }} + +{{- define "appdynamics-cloud-k8s-monitoring.osNodeSelector" }} +nodeSelector: + kubernetes.io/os: {{ . }} +{{- end }} + +{{- define "appdynamics-cloud-k8s-monitoring.getClusterId" }} +{{ if .Values.global.smartAgentInstall -}} +# If installation is via the smartagent, use the special purpose value to set what is being used by the smartagent. +clusterID: {{ "AGENT_PLATFORM_ID_VALUE" }} +{{ else }} +{{- if (lookup "v1" "Namespace" "" "kube-system").metadata }} +clusterID: {{ required "Could not fetch kube-system uid to populate clusterID! " (lookup "v1" "Namespace" "" "kube-system").metadata.uid }} +{{- else -}} +clusterID: {{ .Values.global.clusterId | required "clusterId needs to be specified when kube-system metadata is not accessible!" }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "appdynamics-cloud-k8s-monitoring.getClusterName" }} +{{- if .Values.global.smartAgentInstall -}} +{{ "AGENT_PLATFORM_NAME_VALUE" }} +{{- else }} +{{- .Values.global.clusterName | required "clusterName needs to be specified" }} +{{- end }} +{{- end }} + +{{- define "appdynamics-cloud-k8s-monitoring.getNamespace" }} +{{- if .Values.global.smartAgentInstall -}} +{{- default .Release.Namespace .Values.global.namespace }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} + +{{- define "appdynamics-cloud-k8s-monitoring.getOAuth" }} +oauth: + {{ if .Values.global.smartAgentInstall -}} + # If installation is via the smartagent, use the special purpose value to set what is being used by the smartagent. + clientId: {{ "OAUTH_ID_VALUE" }} + clientSecret: {{ "OAUTH_SECRET_PLAIN_VALUE" }} + endpoint: {{ "SERVICE_DOMAIN_VALUE" }}/data + tokenUrl: {{ "OAUTH_URL_VALUE" }} + {{ else }} + {{ with .Values.global.oauth -}} + # Any one of clientIdEnvVar or clientId is required + {{ if .clientIdEnvVar -}} + clientIdVarSource: {{- toYaml .clientIdEnvVar.valueFrom | nindent 4 }} + {{ else }} + clientId: {{ required "One of clientId or clientIdEnvVar is required when agent management is enabled" .clientId }} + {{- end }} + # Any one of clientSecretEnvVar or clientSecret is required + {{ if .clientSecretEnvVar -}} + clientSecretVarSource: {{- toYaml .clientSecretEnvVar.valueFrom | nindent 4 }} + {{ else }} + clientSecret: {{ required "One of clientSecret or clientSecretEnvVar is required when agent management is enabled" .clientSecret }} + {{- end }} + endpoint: {{ required "endpoint is required" .endpoint }} + tokenUrl: {{ required "tokenUrl is required" .tokenUrl }} + {{- end }} + {{- end }} +{{- end }} + +{{- define "appdynamics-cloud-k8s-monitoring.getAgentManagementProxy" }} +agentManagementProxy: + {{ if .Values.global.smartAgentInstall -}} + # If installation is via the smartagent, use the special purpose value to set what is being used by the smartagent. + httpProxy: {{ "AGENT_HTTP_PROXY_VALUE" }} + httpsProxy: {{ "AGENT_HTTPS_PROXY_VALUE" }} + {{ else }} + {{ with .Values.global.agentManagementProxy -}} + httpProxy: {{ .httpProxy }} + httpsProxy: {{ .httpsProxy }} + noProxy: {{- toYaml .noProxy | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} + +{{- define "appdynamics-cloud-k8s-monitoring.appdLogsCoditionalConfig"}} +conditionalConfigs: + - condition: + or: + - contains: + kubernetes.container.name: logcollector-agent + - contains: + kubernetes.container.name: inframon + - contains: + kubernetes.container.name: clustermon + - contains: + kubernetes.container.name: otc-container + - contains: + kubernetes.pod.name: cloud-operator + - contains: + kubernetes.pod.name: opentelemetry-operator + - contains: + kubernetes.container.name: appdynamics-smartagent + config: + messageParser: + timestamp: + enabled: true + format: ABSOLUTE +{{- end }} + +{{- define "appdynamics-cloud-k8s-monitoring.logCollectorConditionProcessors" }} +{{- if .logFormat}} +- add_fields: + target: appd + fields: + log.format: {{ .logFormat }} +{{- end}} +{{- if .messageParser }} +{{- with .messageParser }} +{{- $numOfDefaultMessageParsersEnabled := 0 }} +{{- $allParsers := (list .logback .log4J .json .grok .infra .multi .timestamp) }} +{{- range $allParsers }} +{{- if . }} +{{- if .enabled }} + {{- $numOfDefaultMessageParsersEnabled = add1 $numOfDefaultMessageParsersEnabled }} +{{- end }} +{{- end }} +{{- end }} +{{- if gt $numOfDefaultMessageParsersEnabled 1 }} +{{- fail "More than one \"enabled\" messageParser is not supported" }} +{{- end }} +- add_fields: + target: _message_parser + fields: + {{- if eq $numOfDefaultMessageParsersEnabled 0}} + type: timestamp + format: "ABSOLUTE" + scan: "true" + + {{- else}} + + {{- if .log4J}} + {{- if .log4J.enabled}} + type: log4j + pattern: {{.log4J.pattern | quote}} + {{- end}} + {{- end}} + + {{- if .logback}} + {{- if .logback.enabled}} + type: logback + pattern: {{.logback.pattern | quote}} + {{- end}} + {{- end}} + + {{- if .json}} + {{- if .json.enabled}} + {{- with .json}} + type: json + timestamp_field: {{if .timestampField}}{{.timestampField | quote}}{{end}} + timestamp_pattern: {{ .timestampPattern | default "yyyy-MM-dd HH:mm:ss,SSS" | quote}} + {{if .flattenSep}}flatten_sep: {{.flattenSep | quote}}{{end}} + {{if .fieldsToIgnore}}fields_to_ignore: {{$first := true}}"{{range .fieldsToIgnore}}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}"{{end}} + {{if .fieldsToIgnore}}fields_to_ignore_sep: ","{{end}} + {{if .fieldsToIgnoreRegex}}fields_to_ignore_regex: {{.fieldsToIgnoreRegex | quote}}{{end}} + {{if .maxNumOfFields}}max_num_of_fields: {{.maxNumOfFields}}{{end}} + {{if .maxDepth}}max_depth: {{.maxDepth}}{{end}} + {{- end}} + {{- end}} + {{- end}} + + {{- if .timestamp}} + {{- if .timestamp.enabled}} + type: timestamp + format: {{.timestamp.format | quote}} + scan: "true" + {{- end}} + {{- end}} + + {{- if .grok}} + {{- if .grok.enabled}} + type: grok + pattern: + {{- range .grok.patterns}} + - {{. | quote}} + {{- end}} + timestamp_field: {{.grok.timestampField | default ""}} + timestamp_format: {{ .grok.timestampPattern | default "yyyy-MM-dd HH:mm:ss,SSS" | quote}} + {{- end}} + {{- end}} + + {{- if .infra}} + {{- if .infra.enabled}} + type: infra + {{- end}} + {{- end}} + + {{- if .multi}} + {{- if .multi.enabled}} + type: multi + parsers: {{.multi.parsers | quote}} + {{- end}} + {{- end}} + + {{- if .grok}} + {{- if and .grok.enabled .subparsers}} + subparsers: {{.subparsers | quote}} + {{- end}} + {{- end}} + {{- end}} +{{- end }} +{{- else }} +- add_fields: + target: _message_parser + fields: + type: timestamp + format: "ABSOLUTE" + scan: "true" +{{- end }} +{{- end }} + +{{- define "appdynamics-cloud-k8s-monitoring.filebeatYml" }} +{{- $clusterName := "" }} +{{- if .Values.global.smartAgentInstall }} +# If installation is via the smartagent, use the special purpose value to set what is being used by the smartagent. +{{- $clusterName = "AGENT_PLATFORM_NAME_VALUE" }} +{{- else }} +{{- $clusterName = .Values.global.clusterName | required "clusterName needs to be specified" }} +{{- end }} +{{- $clusterId := "" }} +{{- if .Values.global.smartAgentInstall }} +# If installation is via the smartagent, use the special purpose value to set what is being used by the smartagent. +{{- $clusterId = "AGENT_PLATFORM_ID_VALUE" }} +{{- else }} +{{- if (lookup "v1" "Namespace" "" "kube-system").metadata }} +{{- $clusterId = (lookup "v1" "Namespace" "" "kube-system").metadata.uid | required "Could not fetch kube-system uid to populate clusterID! " }} +{{- else }} +{{- $clusterId = .Values.global.clusterId | required "clusterId needs to be specified when kube-system metadata is not accessible!" }} +{{- end }} +{{- end }} +{{- $osVal := .osVal }} +{{- $linux := "linux" }} +{{- $windows := "windows" }} +{{- $container:= deepCopy .Values.logCollectorConfig.container}} +{{- $osContainer:= index .Values.logCollectorConfig.env $osVal "container"}} +{{- $containerConfig:= mustMergeOverwrite $container $osContainer}} +{{- if and ($osContainer) (index $container "defaultConfig") }} +{{- $osMessageParser:= index $osContainer "defaultConfig" "messageParser"}} +{{- $_:= set $containerConfig.defaultConfig "messageParser" (coalesce $osMessageParser $containerConfig.defaultConfig.messageParser) }} +{{- end }} +{{- if ( $containerConfig.monitorCollectors)}} +{{- $_:=set $containerConfig "conditionalConfigs" (concat $containerConfig.conditionalConfigs (include "appdynamics-cloud-k8s-monitoring.appdLogsCoditionalConfig" .| fromYaml).conditionalConfigs) }} +{{- end }} +filebeat.autodiscover: + providers: + - type: kubernetes + node: ${NODE_NAME} + labels.dedot: false + annotations.dedot: false + hints.enabled: true + {{- if $containerConfig.defaultConfig.enabled}} + {{- with $containerConfig.defaultConfig}} + hints.default_config: + enabled: true + type: filestream + id: fsid-${data.kubernetes.pod.name}-${data.kubernetes.container.id} + close_removed: false + clean_removed: false + paths: + {{- if eq $osVal $linux }} + - /var/log/containers/${data.kubernetes.pod.name}*${data.kubernetes.container.id}.log + {{- end }} + {{- if eq $osVal $windows }} + - C:/var/log/containers/${data.kubernetes.pod.name}*${data.kubernetes.container.id}.log + {{- end }} + parsers: + - container: + stream: all + format: auto + {{- if .multiLinePattern}} + - multiline: + type: pattern + pattern: {{.multiLinePattern | quote}} + {{- if .multiLineNegate}} + negate: {{.multiLineNegate}} + {{- end}} + match: {{ required "\"multiLineMatch\" field is mandatory, if \"multiLinePattern\" is set." .multiLineMatch }} + {{- end}} + prospector.scanner.symlinks: true + prospector.scanner.exclude_files : [".*(((log)-(collector))|(inframon)|(clustermon)|((otel)-(collect))|((cloud)-(operator))|((opentelemetry)-(operator))|((kube)-)|((fso)-(agent)-(mgmt)))+.*log"] + processors: + {{- include "appdynamics-cloud-k8s-monitoring.logCollectorConditionProcessors" . | nindent 10 }} + {{- end}} + {{- else}} + hints.default_config.enabled: false + {{- end }} + templates: + {{- range $containerConfig.conditionalConfigs}} + - condition: + {{- if .condition}} + {{- if .condition.operator}} + {{.condition.operator}}: + {{.condition.key}}: {{.condition.value}} + {{- else}} + {{ .condition | toYaml | indent 14 | trim }} + {{- end}} + {{- end}} + config: + {{- if .config}} + {{- with .config}} + - type: filestream + id: fsid-${data.kubernetes.pod.name}-${data.kubernetes.container.id} + close_removed: false + clean_removed: false + paths: + {{- if eq $osVal $linux }} + - /var/log/containers/${data.kubernetes.pod.name}*${data.kubernetes.container.id}.log + {{- end }} + {{- if eq $osVal $windows }} + - C:/var/log/containers/${data.kubernetes.pod.name}*${data.kubernetes.container.id}.log + {{- end}} + parsers: + - container: + stream: all + format: auto + {{- if .multiLinePattern}} + - multiline: + type: pattern + pattern: {{.multiLinePattern | quote}} + {{- if .multiLineNegate}} + negate: {{.multiLineNegate}} + {{- end}} + match: {{ required "\"multiLineMatch\" field is mandatory, if \"multiLinePattern\" is set." .multiLineMatch }} + {{- end}} + prospector.scanner.symlinks: true + processors: + {{- include "appdynamics-cloud-k8s-monitoring.logCollectorConditionProcessors" . | nindent 16 }} + {{- end}} + {{- end}} + {{- end}} +{{- with $containerConfig }} +processors: + - add_cloud_metadata: ~ + - add_kubernetes_metadata: + in_cluster: true + host: ${NODE_NAME} + matchers: + - logs_path: + {{- if eq $osVal $linux }} + logs_path: "/var/log/containers/" + {{- end }} + {{- if eq $osVal $windows }} + logs_path: "C:/ProgramData/docker/containers/" + {{- end }} + - copy_fields: + fields: + - from: "kubernetes.deployment.name" + to: "kubernetes.workload.name" + - from: "kubernetes.daemonset.name" + to: "kubernetes.workload.name" + - from: "kubernetes.statefulset.name" + to: "kubernetes.workload.name" + - from: "kubernetes.replicaset.name" + to: "kubernetes.workload.name" + - from: "kubernetes.cronjob.name" + to: "kubernetes.workload.name" + - from: "kubernetes.job.name" + to: "kubernetes.workload.name" + fail_on_error: false + ignore_missing: true + {{- if .excludeCondition}} + - drop_event: + when: + {{ .excludeCondition | toYaml | indent 10 | trim }} + {{- end}} + - rename: + fields: + - from: "kubernetes.namespace" + to: "kubernetes.namespace.name" + - from: "kubernetes" + to: "k8s" + - from: k8s.annotations.appdynamics.lca/filebeat.parser + to: "_message_parser" + - from: "cloud.instance.id" + to: "host.id" + - from: "k8s.container.name" + to: "container.name" + ignore_missing: true + fail_on_error: false + - drop_fields: + fields: ["agent", "stream", "ecs", "input", "orchestrator", "k8s.annotations.appdynamics", "k8s.labels", "k8s.node.labels", "cloud"] + ignore_missing: true + - script: + lang: javascript + source: > + function process(event) { + var podUID = event.Get("k8s.pod.uid"); + if (podUID) { + event.Put("internal.container.encapsulating_object_id", "{{ $clusterId }}:" + podUID); + } + return event; + } + {{- if .dropFields}} + - drop_fields: + fields: [{{range .dropFields}}{{. | quote}}, {{end}}] + ignore_missing: true + {{- end}} + - dissect: + tokenizer: "%{name}:%{tag}" + field: "container.image.name" + target_prefix: "container.image" + ignore_failure: true + overwrite_keys: true + - add_fields: + target: k8s + fields: + cluster.name: {{ $clusterName }} + cluster.id: {{ $clusterId }} + - add_fields: + target: telemetry + fields: + sdk.name: log-agent + - add_fields: + target: os + fields: + type: {{ $osVal }} +output.otlploggrpc: + groupby_resource_fields: + - k8s + - source + - host + - container + - log + - telemetry + - internal + - os + # using the separate LCA logs pipeline's OTLP GRPC receiver port (14317) + hosts: ["${APPD_OTELCOL_GRPC_RECEIVER_HOST}:14317"] + worker: {{.worker}} + max_bytes: {{.maxBytes}} + #hosts: ["otel-collector-local-service.appdynamics.svc.cluster.local:8080"] + {{- with $.Values.global.tls.appdCollectors }} + ssl.enabled: {{.enabled}} + ssl.supported_protocols: [TLSv1.3] + {{- if .enabled}} + {{- if eq $osVal $linux }} + ssl.certificate_authorities: ["/opt/appdynamics/certs/ca/ca.pem"] + ssl.certificate: "/opt/appdynamics/certs/client/client.pem" + ssl.key: "/opt/appdynamics/certs/client/client-key.pem" + {{- end }} + {{- if eq $osVal $windows }} + ssl.certificate_authorities: ["C:/filebeat/certs/ca/ca.pem"] + ssl.certificate: "C:/filebeat/certs/client/client.pem" + ssl.key: "C:/filebeat/certs/client/client-key.pem" + {{- end }} + {{- end}} + {{- end}} + wait_for_ready: true + batch_size: {{.batchSize}} + summary_debug_logs_interval: {{.summaryDebugLogsInterval}} +filebeat.registry.path: registry1 +filebeat.registry.file_permissions: 0640 +{{- if eq $osVal $linux }} +path.data: /opt/appdynamics/logcollector-agent/data +{{- end }} +{{- if eq $osVal $windows }} +path.data: C:/ProgramData/filebeat/data +{{- end}} +{{- with .logging}} +logging: + level: {{.level}} + {{- with .files}} + to_files: {{.enabled}} + files: + {{- if eq $osVal $linux }} + path: /opt/appdynamics/logcollector-agent/log + {{- end }} + {{- if eq $osVal $windows }} + path: C:/ProgramData/filebeat/log + {{- end }} + name: lca-log + keepfiles: {{.keepFiles}} + permissions: 0640 + {{- end}} + selectors: [{{if .metrics.enabled}}monitoring,{{end}}{{range .selectors}}{{.}},{{end}}] + {{- with .metrics}} + metrics: + enabled: {{.enabled}} + period: {{.period}} + {{- end}} +{{- end}} +{{- with .monitoring}} +monitoring: + enabled: {{if $.Values.agentManagementEnabled.logCollector}}{{.otlpmetric.enabled}}{{else}}false{{end}} + {{- if .otlpmetric.enabled}} + {{- with .otlpmetric}} + otlpmetric: + endpoint: {{.endpoint}} + protocol: {{.protocol}} + collect_period: {{.collectPeriod}} + report_period: {{.reportPeriod}} + resource_attributes: + {{- range .resourceAttrs}} + {{.key}}: {{.value | quote}} + {{- end}} + {{- if (gt (len .metrics) 0)}} + metrics: + {{- range .metrics}} + - {{.}} + {{- end}} + {{- end}} + {{- if .retry.enabled}} + {{- with .retry}} + retry: + enabled: {{.enabled}} + initial_interval: {{.initialInterval}} + max_interval: {{.maxInterval}} + max_elapsed_time: {{.maxElapsedTime}} + {{- end}} + {{- end}} + {{- with $.Values.global.tls.appdCollectors }} + ssl.enabled: {{.enabled}} + ssl.supported_protocols: [TLSv1.3] + {{- if .enabled}} + {{- if eq $osVal $linux }} + ssl.certificate_authorities: ["/opt/appdynamics/certs/ca/ca.pem"] + ssl.certificate: "/opt/appdynamics/certs/client/client.pem" + ssl.key: "/opt/appdynamics/certs/client/client-key.pem" + {{- end }} + {{- if eq $osVal $windows }} + ssl.certificate_authorities: ["C:/filebeat/certs/ca/ca.pem"] + ssl.certificate: "C:/filebeat/certs/client/client.pem" + ssl.key: "C:/filebeat/certs/client/client-key.pem" + {{- end }} + {{- end}} + {{- end}} + {{- end}} + {{- end}} +{{- end}} +{{- end}} +{{- end}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/clustermon.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/clustermon.yaml new file mode 100644 index 00000000..3a890fab --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/clustermon.yaml @@ -0,0 +1,107 @@ +{{ if .Values.install.clustermon -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: Clustermon +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-clustermon" | trunc 63 }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +spec: + {{- $mergedPodConfig := .Values.clustermonPod }} + {{- if (index $mergedPodConfig "nodeSelector" "kubernetes.io/os") }} + {{- if ne (index $mergedPodConfig "nodeSelector" "kubernetes.io/os") .Values.clustermonConfig.os }} + {{- fail "Invalid node selector" }} + {{- end }} + {{- else }} + {{- $mergedPodConfig := mustMergeOverwrite (include "appdynamics-cloud-k8s-monitoring.osNodeSelector" .Values.clustermonConfig.os | fromYaml ) $mergedPodConfig }} + {{- end }} + {{- template "appdynamics-cloud-k8s-monitoring.podConfigs" $mergedPodConfig }} + + serviceAccountName: {{ .Values.clustermonServiceAccount}} + + {{ with .Values.global.tls.appdCollectors -}} + mTLS: + enabled: {{ .enabled | quote }} + {{ if .enabled -}} + secretName: {{ required "A valid secret name entry required!" .secret.secretName }} + secretKeys: + caCert: {{ .secret.secretKeys.caCert }} + tlsCert: {{ .secret.secretKeys.tlsCert }} + tlsKey: {{ .secret.secretKeys.tlsKey }} + {{- end }} + {{- end }} + + agentManagementEnabled: {{ .Values.agentManagementEnabled.clustermon | quote }} + {{ if .Values.agentManagementEnabled.clustermon -}} + {{- include "appdynamics-cloud-k8s-monitoring.getOAuth" . | nindent 2 }} + {{- include "appdynamics-cloud-k8s-monitoring.getAgentManagementProxy" . | nindent 2 }} + {{- end }} + collectorName: {{ .Release.Name }} + + clusterName: {{ include "appdynamics-cloud-k8s-monitoring.getClusterName" . }} + helmChartVersion: {{ .Values.global.helmChartVersion }} + {{- include "appdynamics-cloud-k8s-monitoring.getClusterId" . | nindent 2 }} + {{ with .Values.clustermonConfig -}} + os: {{ .os }} + logLevel: {{ .logLevel }} + logFilesMaxSizeMb: {{ .logFilesMaxSizeMb }} + logFilesNumBackups: {{ .logFilesNumBackups }} + printToStdout: {{ .printToStdout | quote }} + {{ if .gatherInterval -}} + gatherInterval: {{ .gatherInterval }} + {{- end }} + {{ if .maxGoRoutine -}} + maxGoRoutine: {{ .maxGoRoutine }} + {{- end }} + + filters: + namespace: + {{- toYaml .filters.namespace | nindent 6 }} + entity: + {{- toYaml .filters.entity | nindent 6 }} + label: + {{- toYaml .filters.label | nindent 6 }} + annotation: + {{- toYaml .filters.annotation | nindent 6}} + scopedFilters: + {{- toYaml .filters.scopedFilters | nindent 6}} + + {{ if .testSetupEnabled -}} + testSetupEnabled: {{ .testSetupEnabled | quote }} + {{- end }} + {{ if .optimisedPayloadInterval -}} + optimisedPayloadInterval: {{ .optimisedPayloadInterval }} + {{- end }} + {{ if .events -}} + events: + enabled: {{ .events.enabled | quote }} + severityToExclude: + {{- toYaml .events.severityToExclude | nindent 6 }} + reasonToExclude: + {{- toYaml .events.reasonToExclude | nindent 6 }} + severeGroupByReason: + {{- toYaml .events.severeGroupByReason | nindent 6 }} + {{- end }} + + labelsIngestionEnabled: {{ .labels.enabled }} + configurationEnabled: {{ .configurations.enabled | quote }} + hpaVpaEnabled: {{ .autoscalers.hpaVpaEnabled | quote }} + + {{ if .profiler -}} + profiler: + enabled: {{ .profiler.enabled | quote }} + port: {{ .profiler.port }} + {{- end }} + + + ingressControllers: + {{- toYaml .ingressControllers | nindent 4 }} + {{- end }} + + {{ with .Values.infraManagerConfig -}} + infraManagerConfig: + logFilesMaxSizeMb: {{ .logFilesMaxSizeMb }} + logFilesNumBackups: {{ .logFilesNumBackups }} + printToStdout: {{ .printToStdout | quote }} + logLevel: {{ .logLevel }} + {{- end }} + +{{ end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/containermon.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/containermon.yaml new file mode 100644 index 00000000..28f8abba --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/containermon.yaml @@ -0,0 +1,46 @@ +{{ if and .Values.install.defaultInfraCollectors (has "linux" .Values.containermonConfig.os) -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: Containermon +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-containermon" | trunc 63 }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +spec: + os: linux + {{- include "appdynamics-cloud-k8s-monitoring.getClusterId" . | nindent 2 }} + {{$containermonConfig := .Values.containermonConfig}} + {{ if (.Values.containermonConfig.env).linux -}} + {{$containermonConfig = mustMergeOverwrite .Values.containermonConfig .Values.containermonConfig.env.linux}} + {{- end }} + {{ with $containermonConfig -}} + {{ if .gatherInterval -}} + gatherInterval: {{ .gatherInterval }} + {{- end }} + logFilesMaxSizeMb: {{ .logFilesMaxSizeMb }} + logFilesNumBackups: {{ .logFilesNumBackups }} + logLevel: {{ .logLevel }} + {{- end }} +{{- end }} +--- +{{ if and .Values.install.defaultInfraCollectors (has "windows" .Values.containermonConfig.os) -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: Containermon +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-containermon-windows" | trunc 63 }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +spec: + os: windows + {{- include "appdynamics-cloud-k8s-monitoring.getClusterId" . | nindent 2 }} + {{$containermonConfig := .Values.containermonConfig}} + {{ if (.Values.containermonConfig.env).windows -}} + {{$containermonConfig = mustMergeOverwrite .Values.containermonConfig .Values.containermonConfig.env.windows}} + {{- end }} + {{ with $containermonConfig -}} + {{ if .gatherInterval -}} + gatherInterval: {{ .gatherInterval }} + {{- end }} + logFilesMaxSizeMb: {{ .logFilesMaxSizeMb }} + logFilesNumBackups: {{ .logFilesNumBackups }} + logLevel: {{ .logLevel }} + {{- end }} +{{- end }} + diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/inframon.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/inframon.yaml new file mode 100644 index 00000000..a6b20715 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/inframon.yaml @@ -0,0 +1,107 @@ +{{ if and .Values.install.defaultInfraCollectors (or (has "linux" .Values.containermonConfig.os) (has "linux" .Values.servermonConfig.os)) -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: Inframon +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-inframon" | trunc 63 }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +spec: + {{- $mergedPodConfig := (mustMergeOverwrite .Values.inframonPod .Values.inframonPod.env.linux) }} + {{- if (index $mergedPodConfig "nodeSelector" "kubernetes.io/os") }} + {{- if ne (index $mergedPodConfig "nodeSelector" "kubernetes.io/os") "linux" }} + {{- fail "Invalid node selector" }} + {{- end }} + {{- else }} + {{- $mergedPodConfig := mustMergeOverwrite (include "appdynamics-cloud-k8s-monitoring.osNodeSelector" "linux" | fromYaml ) $mergedPodConfig }} + {{- end }} + {{- template "appdynamics-cloud-k8s-monitoring.podConfigs" $mergedPodConfig }} + os: linux + serviceAccountName: {{ .Values.inframonServiceAccount}} + + {{ with .Values.global.tls.appdCollectors -}} + mTLS: + enabled: {{ .enabled | quote }} + {{ if .enabled -}} + secretName: {{ required "A valid secret name entry required!" .secret.secretName }} + secretKeys: + caCert: {{ .secret.secretKeys.caCert }} + tlsCert: {{ .secret.secretKeys.tlsCert }} + tlsKey: {{ .secret.secretKeys.tlsKey }} + {{- end }} + {{- end }} + + agentManagementEnabled: {{ .Values.agentManagementEnabled.defaultInfraCollectors | quote }} + {{ if .Values.agentManagementEnabled.defaultInfraCollectors -}} + collectorName: {{ .Release.Name }} + clusterName: {{ include "appdynamics-cloud-k8s-monitoring.getClusterName" . }} + helmChartVersion: {{ .Values.global.helmChartVersion }} + {{- include "appdynamics-cloud-k8s-monitoring.getClusterId" . | nindent 2 }} + {{- include "appdynamics-cloud-k8s-monitoring.getOAuth" . | nindent 2 }} + {{- include "appdynamics-cloud-k8s-monitoring.getAgentManagementProxy" . | nindent 2 }} + {{- end }} + + {{ with .Values.infraManagerConfig -}} + logFilesMaxSizeMb: {{ .logFilesMaxSizeMb }} + logFilesNumBackups: {{ .logFilesNumBackups }} + printToStdout: {{ .printToStdout | quote }} + logLevel: {{ .logLevel }} + {{- end }} +{{- end }} +--- +{{ if and .Values.install.defaultInfraCollectors (or (has "windows" .Values.containermonConfig.os) (has "windows" .Values.servermonConfig.os)) -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: Inframon +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-inframon-windows" | trunc 63 }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +spec: + {{- $mergedPodConfig := (mustMergeOverwrite .Values.inframonPod .Values.inframonPod.env.windows) }} + {{- if (index $mergedPodConfig "nodeSelector" "kubernetes.io/os") }} + {{- if ne (index $mergedPodConfig "nodeSelector" "kubernetes.io/os") "windows" }} + {{- fail "Invalid node selector" }} + {{- end }} + {{- else }} + {{- $mergedPodConfig := mustMergeOverwrite (include "appdynamics-cloud-k8s-monitoring.osNodeSelector" "windows" | fromYaml ) $mergedPodConfig }} + {{- end }} + {{- template "appdynamics-cloud-k8s-monitoring.podConfigs" $mergedPodConfig }} + + os: windows + serviceAccountName: {{ .Values.inframonServiceAccount}} + + {{ with .Values.global.tls.appdCollectors -}} + mTLS: + enabled: {{ .enabled | quote }} + {{ if .enabled -}} + secretName: {{ required "A valid secret name entry required!" .secret.secretName }} + secretKeys: + caCert: {{ .secret.secretKeys.caCert }} + tlsCert: {{ .secret.secretKeys.tlsCert }} + tlsKey: {{ .secret.secretKeys.tlsKey }} + {{- end }} + {{- end }} + + agentManagementEnabled: {{ .Values.agentManagementEnabled.defaultInfraCollectors | quote }} + {{ if .Values.agentManagementEnabled.defaultInfraCollectors -}} + collectorName: {{ .Release.Name }} + clusterName: {{ include "appdynamics-cloud-k8s-monitoring.getClusterName" . }} + helmChartVersion: {{ .Values.global.helmChartVersion }} + {{- include "appdynamics-cloud-k8s-monitoring.getClusterId" . | nindent 2 }} + {{- include "appdynamics-cloud-k8s-monitoring.getOAuth" . | nindent 2 }} + {{- include "appdynamics-cloud-k8s-monitoring.getAgentManagementProxy" . | nindent 2 }} + {{- end }} + + {{ with .Values.infraManagerConfig -}} + logFilesMaxSizeMb: {{ .logFilesMaxSizeMb }} + logFilesNumBackups: {{ .logFilesNumBackups }} + printToStdout: {{ .printToStdout | quote }} + logLevel: {{ .logLevel }} + {{- end }} + + windowsExporter: + {{- $mergedPodConfig := .Values.windowsExporterPod }} + {{- if (index $mergedPodConfig "nodeSelector" "kubernetes.io/os") }} + {{- if ne (index $mergedPodConfig "nodeSelector" "kubernetes.io/os") "windows" }} + {{- fail "Invalid node selector" }} + {{- end }} + {{- end }} + {{- include "appdynamics-cloud-k8s-monitoring.podConfigs" $mergedPodConfig | nindent 2 }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/logCollector.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/logCollector.yaml new file mode 100644 index 00000000..fd9365ba --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/logCollector.yaml @@ -0,0 +1,87 @@ +{{$linux :="linux"}} +{{$windows :="windows"}} +{{ if and (.Values.install.logCollector) (has $linux .Values.logCollectorConfig.os) -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: LogCollector +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-log-collector" | trunc 63 }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +spec: + {{- template "appdynamics-cloud-k8s-monitoring.podConfigs" (mustMergeOverwrite .Values.logCollectorPod .Values.logCollectorPod.env.linux) }} + os: {{$linux}} + serviceAccountName: {{ .Values.logCollectorServiceAccount}} + rollingUpdateMaxUnavailable: {{ .Values.logCollectorPod.rollingUpdateMaxUnavailable}} + + {{ with .Values.global.tls.appdCollectors -}} + mTLS: + enabled: {{ .enabled | quote }} + {{ if .enabled -}} + secretName: {{ required "A valid secret name entry required!" .secret.secretName }} + secretKeys: + caCert: {{ .secret.secretKeys.caCert }} + tlsCert: {{ .secret.secretKeys.tlsCert }} + tlsKey: {{ .secret.secretKeys.tlsKey }} + {{- end }} + {{- end }} + + {{ if (coalesce .Values.logCollectorConfig.env.linux.filebeatYaml .Values.logCollectorConfig.filebeatYaml ) -}} + filebeatYaml: {{ (coalesce .Values.logCollectorConfig.env.linux.filebeatYaml .Values.logCollectorConfig.filebeatYaml ) | quote }} + {{ else -}} + {{$data := dict "osVal" $linux "Values" .Values }} + filebeatYaml: |- + {{- include "appdynamics-cloud-k8s-monitoring.filebeatYml" $data | nindent 8}} + {{- end }} + + agentManagementEnabled: {{ .Values.agentManagementEnabled.logCollector | quote }} + {{ if .Values.agentManagementEnabled.logCollector -}} + collectorName: {{ .Release.Name }} + clusterName: {{ include "appdynamics-cloud-k8s-monitoring.getClusterName" . }} + helmChartVersion: {{ .Values.global.helmChartVersion }} + {{- include "appdynamics-cloud-k8s-monitoring.getClusterId" . | nindent 2 }} + {{- include "appdynamics-cloud-k8s-monitoring.getOAuth" . | nindent 2 }} + {{- include "appdynamics-cloud-k8s-monitoring.getAgentManagementProxy" . | nindent 2 }} + {{- end }} +{{- end }} +--- +{{ if and (.Values.install.logCollector) (has $windows .Values.logCollectorConfig.os) -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: LogCollector +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-log-collector-windows" | trunc 63 }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +spec: + {{- template "appdynamics-cloud-k8s-monitoring.podConfigs" (mustMergeOverwrite .Values.logCollectorPod .Values.logCollectorPod.env.windows) }} + os: {{$windows}} + serviceAccountName: {{ .Values.logCollectorServiceAccount}} + + {{ with .Values.global.tls.appdCollectors -}} + mTLS: + enabled: {{ .enabled | quote }} + {{ if .enabled -}} + secretName: {{ required "A valid secret name entry required!" .secret.secretName }} + secretKeys: + caCert: {{ .secret.secretKeys.caCert }} + tlsCert: {{ .secret.secretKeys.tlsCert }} + tlsKey: {{ .secret.secretKeys.tlsKey }} + {{- end }} + {{- end }} + + {{ if (coalesce .Values.logCollectorConfig.env.windows.filebeatYaml .Values.logCollectorConfig.filebeatYaml ) -}} + filebeatYaml: |- + {{- (coalesce .Values.logCollectorConfig.env.windows.filebeatYaml .Values.logCollectorConfig.filebeatYaml ) | nindent 8 }} + {{ else -}} + {{$data := dict "osVal" $windows "Values" .Values }} + filebeatYaml: |- + {{- include "appdynamics-cloud-k8s-monitoring.filebeatYml" $data | nindent 8}} # appdynamics-cloud-k8s-monitoring.filebeatYml change this when simplified/default config + {{- end }} + + agentManagementEnabled: {{ .Values.agentManagementEnabled.logCollector | quote }} + {{ if .Values.agentManagementEnabled.logCollector -}} + collectorName: {{ .Release.Name }} + clusterName: {{ include "appdynamics-cloud-k8s-monitoring.getClusterName" . }} + helmChartVersion: {{ .Values.global.helmChartVersion }} + {{- include "appdynamics-cloud-k8s-monitoring.getClusterId" . | nindent 2 }} + {{- include "appdynamics-cloud-k8s-monitoring.getOAuth" . | nindent 2 }} + {{- include "appdynamics-cloud-k8s-monitoring.getAgentManagementProxy" . | nindent 2 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_clusterrole.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_clusterrole.yaml new file mode 100644 index 00000000..66bec137 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_clusterrole.yaml @@ -0,0 +1,73 @@ +{{ if .Values.install.clustermon -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: appdynamics-clustermon-clusterrole +rules: +- apiGroups: + - "" + resources: + - endpoints + - services + - events + - namespaces + - nodes + - nodes/proxy + - pods + - resourcequotas + - persistentvolumeclaims + - persistentvolumes + - replicationcontrollers +{{- if .Values.clustermonConfig.configurations.enabled }} + - configmaps + - secrets +{{- end }} + verbs: + - get + - list + - watch +- apiGroups: + - apps + resources: + - daemonsets + - deployments + - replicasets + - statefulsets + verbs: + - get + - list + - watch +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch +- apiGroups: + - batch + resources: + - cronjobs + - jobs + verbs: + - get + - list + - watch +- apiGroups: + - autoscaling.k8s.io + resources: + - verticalpodautoscalers + verbs: + - get + - list + - watch +- apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - get + - list + - watch +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_clusterrole_binding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_clusterrole_binding.yaml new file mode 100644 index 00000000..35aa516a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_clusterrole_binding.yaml @@ -0,0 +1,14 @@ +{{ if .Values.install.clustermon -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: appdynamics-clustermon-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: appdynamics-clustermon-clusterrole +subjects: + - kind: ServiceAccount + name: {{ .Values.clustermonServiceAccount }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_openshift_scc.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_openshift_scc.yaml new file mode 100644 index 00000000..55cb71b8 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_openshift_scc.yaml @@ -0,0 +1,24 @@ +{{ if .Values.install.clustermon -}} +{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1/SecurityContextConstraints" -}} +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + annotations: + kubernetes.io/description: 'clustermon-privileged-scc is a custom SCC for AppDynamics Cloud Cluster Collector' + name: clustermon-privileged-scc + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegedContainer: false +readOnlyRootFilesystem: false +runAsUser: + type: RunAsAny +seLinuxContext: + type: MustRunAs +users: + - system:serviceaccount:{{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }}:{{ .Values.clustermonServiceAccount }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_service_account.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_service_account.yaml new file mode 100644 index 00000000..25b64e39 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_service_account.yaml @@ -0,0 +1,7 @@ +{{ if .Values.install.clustermon -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.clustermonServiceAccount }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_clusterrole.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_clusterrole.yaml new file mode 100644 index 00000000..3ecff48c --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_clusterrole.yaml @@ -0,0 +1,22 @@ +{{ if .Values.install.defaultInfraCollectors -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: appdynamics-inframon-clusterrole +rules: +- apiGroups: + - "" + resources: + - nodes + - nodes/proxy + verbs: + - get +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_clusterrole_binding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_clusterrole_binding.yaml new file mode 100644 index 00000000..117e7051 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_clusterrole_binding.yaml @@ -0,0 +1,14 @@ +{{ if .Values.install.defaultInfraCollectors -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: appdynamics-inframon-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: appdynamics-inframon-clusterrole +subjects: + - kind: ServiceAccount + name: {{ .Values.inframonServiceAccount }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_openshift_scc.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_openshift_scc.yaml new file mode 100644 index 00000000..1105d524 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_openshift_scc.yaml @@ -0,0 +1,24 @@ +{{ if .Values.install.defaultInfraCollectors -}} +{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1/SecurityContextConstraints" -}} +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + annotations: + kubernetes.io/description: 'inframon-privileged-scc is a custom SCC for AppDynamics Cloud Infrastructure Collector' + name: inframon-privileged-scc + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +allowHostDirVolumePlugin: true +allowHostIPC: false +allowHostNetwork: true +allowHostPID: false +allowHostPorts: false +allowPrivilegedContainer: false +readOnlyRootFilesystem: false +runAsUser: + type: RunAsAny +seLinuxContext: + type: MustRunAs +users: + - system:serviceaccount:{{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }}:{{ .Values.inframonServiceAccount }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_service_account.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_service_account.yaml new file mode 100644 index 00000000..bb6a0ac2 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_service_account.yaml @@ -0,0 +1,7 @@ +{{ if .Values.install.defaultInfraCollectors -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.inframonServiceAccount }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_clusterrole.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_clusterrole.yaml new file mode 100644 index 00000000..7dd13fce --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_clusterrole.yaml @@ -0,0 +1,33 @@ +{{ if .Values.install.logCollector -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: appdynamics-logcollector-clusterrole +rules: +- apiGroups: + - "" + resources: + - namespaces + - pods + - nodes + verbs: + - get + - watch + - list +- apiGroups: + - apps + resources: + - replicasets + verbs: + - get + - list + - watch +- apiGroups: + - batch + resources: + - jobs + verbs: + - get + - watch + - list +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_clusterrole_binding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_clusterrole_binding.yaml new file mode 100644 index 00000000..90246d79 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_clusterrole_binding.yaml @@ -0,0 +1,14 @@ +{{ if .Values.install.logCollector -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: appdynamics-logcollector-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: appdynamics-logcollector-clusterrole +subjects: + - kind: ServiceAccount + name: {{ .Values.logCollectorServiceAccount }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_openshift_scc.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_openshift_scc.yaml new file mode 100644 index 00000000..cfb58b39 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_openshift_scc.yaml @@ -0,0 +1,32 @@ +{{ if .Values.install.logCollector -}} +{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1/SecurityContextConstraints" -}} +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + annotations: + kubernetes.io/description: 'logcollector-privileged-scc is a custom SCC for AppDynamics Cloud Log Collector' + name: logcollector-privileged-scc + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +allowHostDirVolumePlugin: true +allowHostIPC: false +allowHostNetwork: true +allowHostPID: false +allowHostPorts: false +allowPrivilegedContainer: false +readOnlyRootFilesystem: true +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +users: + - system:serviceaccount:{{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }}:{{ .Values.logCollectorServiceAccount }} +volumes: + - configMap + - hostPath # LCA uses hostPath for config and registry files + - secret + - emptyDir + - downwardAPI + - persistentVolumeClaim + - projected +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_service_account.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_service_account.yaml new file mode 100644 index 00000000..d917f7ba --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_service_account.yaml @@ -0,0 +1,7 @@ +{{ if .Values.install.logCollector -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.logCollectorServiceAccount }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/servermon.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/servermon.yaml new file mode 100644 index 00000000..591b25e2 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/servermon.yaml @@ -0,0 +1,61 @@ +{{ if and .Values.install.defaultInfraCollectors (has "linux" .Values.servermonConfig.os) -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: Servermon +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-servermon" | trunc 63 }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +spec: + os: linux + {{$servermonConfig := .Values.servermonConfig}} + {{ if (.Values.servermonConfig.env).linux -}} + {{$servermonConfig = mustMergeOverwrite .Values.servermonConfig .Values.servermonConfig.env.linux}} + {{- end }} + {{ with $servermonConfig -}} + {{ if .gatherInterval -}} + gatherInterval: {{ .gatherInterval }} + {{- end }} + logFilesMaxSizeMb: {{ .logFilesMaxSizeMb }} + logFilesNumBackups: {{ .logFilesNumBackups }} + logLevel: {{ .logLevel }} + + {{ if .skipProviderCheck -}} + skipProviderCheck: {{ .skipProviderCheck | quote }} + {{- end }} + + {{ if .exporterPort -}} + exporterPort: {{ .exporterPort }} + {{- end }} + + {{- end }} +{{- end }} +--- +{{ if and .Values.install.defaultInfraCollectors (has "windows" .Values.servermonConfig.os) -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: Servermon +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-servermon-windows" | trunc 63 }} + namespace: {{ include "appdynamics-cloud-k8s-monitoring.getNamespace" . }} +spec: + os: windows + {{$servermonConfig := .Values.servermonConfig}} + {{ if (.Values.servermonConfig.env).windows -}} + {{$servermonConfig = mustMergeOverwrite .Values.servermonConfig .Values.servermonConfig.env.windows}} + {{- end }} + {{ with $servermonConfig -}} + {{ if .gatherInterval -}} + gatherInterval: {{ .gatherInterval }} + {{- end }} + logFilesMaxSizeMb: {{ .logFilesMaxSizeMb }} + logFilesNumBackups: {{ .logFilesNumBackups }} + logLevel: {{ .logLevel }} + + {{ if .skipProviderCheck -}} + skipProviderCheck: {{ .skipProviderCheck | quote }} + {{- end }} + + {{ if .exporterPort -}} + exporterPort: {{ .exporterPort }} + {{- end }} + + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/values.schema.json b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/values.schema.json new file mode 100644 index 00000000..94d93d6f --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/values.schema.json @@ -0,0 +1,1499 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "title": "Values", + "additionalProperties": false, + "properties": { + "global": { + "type": "object", + "additionalProperties": false, + "properties": { + "smartAgentInstall": { + "description": "enabled when installed via smartagent. Installation takes all the common values used by the smartagent.", + "type": "boolean" + }, + "namespace": { + "description": "namespace to use when installed via smartagent", + "type": "string" + }, + "helmChartVersion": { + "description": "version of helm chart", + "type": "string" + }, + "clusterName": { + "description": "name of cluster", + "type": "string" + }, + "clusterId": { + "description": "The uid of kube-system namespace, required when helm lookup is not supported", + "type": "string" + }, + "oauth": { + "type": "object", + "properties": { + "clientId": { + "type": "string", + "description": "AppDynamics oauth2 client id" + }, + "clientSecret": { + "type": "string", + "description": "AppDynamics oauth2 client secret plain text" + }, + "clientIdEnvVar": { + "type": "object", + "additionalProperties": false, + "description": "The clientIdEnvVar Schema", + "properties": { + "valueFrom": { + "type": "object", + "properties": { + "secretKeyRef": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "key": { + "type": "string" + } + } + } + } + } + } + }, + "clientSecretEnvVar": { + "type": "object", + "description": "The clientSecretEnvVar Schema", + "properties": { + "valueFrom": { + "type": "object", + "properties": { + "secretKeyRef": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "key": { + "type": "string" + } + } + } + } + } + } + }, + "endpoint": { + "type": "string", + "description": "AppDynamics endpoint url" + }, + "tokenUrl": { + "type": "string", + "description": "AppDynamics oauth2 token refresh url" + } + }, + "allOf": [ + { + "anyOf": [ + { + "required": ["clientSecret"] + }, + { + "required": ["clientSecretEnvVar"] + } + ] + }, + { + "anyOf": [ + { + "required": ["clientId"] + }, + { + "required": ["clientIdEnvVar"] + } + ] + } + ] + }, + "agentManagementProxy": { + "type": "object", + "properties": { + "httpProxy": { + "type": "string", + "description": "http proxy for agent management" + }, + "httpsProxy": { + "type": "string", + "description": "https proxy for agent management" + }, + "noProxy": { + "type": "array", + "description": "hostnames to skip proxying the request for agent management", + "items": { + "type": "string" + } + } + } + }, + "tls": { + "type": "object", + "properties": { + "appdCollectors": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "description": "enable TLS for communication between Cisco AppDynamics Collectors and the Cisco AppDynamics Distribution of OpenTelemetry Collector (service).", + "type": "boolean" + }, + "secret": { + "type": "object", + "additionalProperties": false, + "properties": { + "secretName": { + "description": "name of the Kubernetes secret that holds the certificates", + "type": "string" + }, + "secretKeys": { + "description": "secret keys for specifying TLS certificate, key, and CA certificate", + "type": "object", + "additionalProperties": false, + "properties": { + "caCert": { + "description": "kubernetes secret key name that points to the CA certificate", + "type": "string" + }, + "tlsCert": { + "description": "kubernetes secret key name that points to the TLS certificate", + "type": "string" + }, + "tlsKey": { + "description": "kubernetes secret key name that points to the TLS key", + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "install": { + "description": "contain flags to control installation of cluster collector, infra collector and log collector", + "type": "object", + "additionalProperties": false, + "properties": { + "clustermon": { + "type": "boolean" + }, + "defaultInfraCollectors": { + "type": "boolean" + }, + "logCollector": { + "type": "boolean" + } + }, + "required": [ + "clustermon", + "defaultInfraCollectors", + "logCollector" + ] + }, + "agentManagementEnabled": { + "description": "opt in and out from Agent Management for cluster collector, infra collector and log collector", + "type": "object", + "additionalProperties": false, + "properties": { + "clustermon": { + "type": "boolean" + }, + "defaultInfraCollectors": { + "type": "boolean" + }, + "logCollector": { + "type": "boolean" + } + } + }, + "clustermonServiceAccount": { + "description": "serviceAccount name for clustermon", + "type": "string" + }, + "inframonServiceAccount": { + "description": "serviceAccount name for inframon", + "type": "string" + }, + "logCollectorServiceAccount": { + "description": "serviceAccount name for log collector", + "type": "string" + }, + "clustermonConfig": { + "description": "configuration for clustermon", + "type": "object", + "additionalProperties": false, + "properties": { + "logLevel": { + "description": "log level for cluster collector", + "type": "string" + }, + "logFilesMaxSizeMb": { + "description": "maximum size of one log file (in MB)", + "type": "integer" + }, + "logFilesNumBackups": { + "description": "maximum number of log files created before overwriting the oldest one", + "type": "integer" + }, + "os": { + "description": "operating system of the nodes on which cluster collector will be installed", + "type": "string", + "enum": ["linux", "windows"] + }, + "printToStdout": { + "description": "Whether Kubernetes logs will report logs.", + "type": "string" + }, + "filters": { + "description": "filters based on namespace, entity and label for monitoring K8s objects", + "type": "object", + "additionalProperties": false, + "properties": { + "namespace": { + "type": "object", + "additionalProperties": false, + "properties": { + "includeRegex": { + "type": "string" + }, + "excludeRegex": { + "type": "string" + } + } + }, + "entity": { + "type": "object", + "additionalProperties": false, + "properties": { + "excludeRegex": { + "type": "string" + }, + "excludeLabels": { + "type": "array", + "items": { + "type": "object" + } + } + } + }, + "label": { + "type": "object", + "additionalProperties": false, + "properties": { + "excludeRegex": { + "type": "string" + } + } + }, + "annotation": { + "type": "object", + "additionalProperties": false, + "properties": { + "excludeRegex": { + "type": "string" + } + } + }, + "scopedFilters": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "scope": { + "type": "object", + "additionalProperties": false, + "properties": { + "namespaceRegex": { + "type": "string" + }, + "entityTypes": { + "type": "array", + "items": { + "type": "string", + "enum": ["configmap", "cronjob", "daemonset", "deployment", "horizontalpodautoscaler", "job", "replicaset", "replicationcontroller", "secret", "statefulset"] + } + } + } + }, + "entityFilter": { + "type": "object", + "additionalProperties": false, + "properties": { + "excludeRegex": { + "type": "string" + }, + "excludeLabels": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, + "ingressControllers": { + "description": "ingressControllers property", + "type": "object" + }, + "events": { + "description": "configuration for collecting events", + "type": "object" + }, + "configurations": { + "description": "enable or disable monitoring Configurations (ConfigMap, Secret)", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "maxGoRoutine": { + "description": "maximum number of go routines used", + "type": "integer", + "minimum": 1, + "maximum": 10 + }, + "helmChartVersion": { + "description": "version of the helm chart used", + "type": "string" + }, + "labels": { + "description": "allows you to enable or disable labels collection", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "autoscalers": { + "description": "allows you to enable or disable monitoring autoscalers (hpa)", + "type": "object", + "additionalProperties": false, + "properties": { + "hpaVpaEnabled": { + "type": "boolean" + } + } + }, + "profiler": { + "description": "allow you to enable or disable profiler", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + } + } + } + } + }, + "infraManagerConfig": { + "description": "configuration for infra manager", + "type": "object", + "additionalProperties": false, + "properties": { + "logLevel": { + "description": "log level for infra manager", + "type": "string" + }, + "logFilesMaxSizeMb": { + "description": "maximum size of one log file for infra manager", + "type": "number" + }, + "logFilesNumBackups": { + "description": "maximum number of log files created for infra manager before overwriting the oldest one", + "type": "number" + }, + "printToStdout": { + "description": "determines whether infra manager logs report through Kubernetes logs", + "type": "string" + } + } + }, + "servermonConfig": { + "description": "configuration for server collector", + "type": "object", + "additionalProperties": false, + "properties": { + "os": { + "description": "operating system of the nodes on which server collector will be installed", + "type": "array", + "items": { + "type": "string", + "enum": ["linux", "windows"] + } + }, + "logLevel": { + "description": "log level for server collector", + "type": "string" + }, + "logFilesMaxSizeMb": { + "description": "maximum size of one log file for server collector", + "type": "number" + }, + "logFilesNumBackups": { + "description": "maximum number of log files created for server collector before overwriting the oldest one", + "type": "number" + }, + "exporterPort": { + "description": "port used to start Node Exporter in Linux", + "type": "number" + }, + "gatherInterval": { + "description": "gather interval for server collector", + "type": "number", + "enum": [10, 20, 30, 60] + }, + "skipProviderCheck": { + "description": "skip the cloud provider check in server collector", + "type": "boolean" + }, + "env": { + "description": "override the server collector configuration for a specific operating system", + "type": "object" + } + }, + "required": [ + "os" + ] + }, + "containermonConfig": { + "description": "configuration for container collector", + "type": "object", + "additionalProperties": false, + "properties": { + "os": { + "description": "operating system of the nodes on which container collector will be installed", + "type": "array", + "items": { + "type": "string", + "enum": ["linux", "windows"] + } + }, + "logLevel": { + "description": "log level for container collector", + "type": "string" + }, + "logFilesMaxSizeMb": { + "description": "maximum size of one log file for container collector", + "type": "number" + }, + "logFilesNumBackups": { + "description": "maximum number of log files created for container collector before overwriting the oldest one", + "type": "number" + }, + "gatherInterval": { + "description": "gather interval for container collector", + "type": "number", + "enum": [10, 20, 30, 60] + }, + "env": { + "description": "override the container collector configuration for a specific operating system", + "type": "object" + } + }, + "required": [ + "os" + ] + }, + "logCollectorConfig": { + "description": "configuration for log collector", + "type": "object", + "additionalProperties": false, + "properties": { + "os": { + "description": "OS on which Log Collector should be deployed, accepted values are linux and windows", + "type": "array", + "items": { + "type": "string" + } + }, + "env": { + "description": "Specifies OS-specific overrides.", + "type": "object", + "additionalProperties": false, + "properties": { + "linux": { + "type": "object", + "additionalProperties": false, + "properties": { + "container": { + "$ref": "#/definitions/logCollectorConfigContainerProp" + }, + "filebeatYaml": { + "description": "Advanced config for LCA", + "type": "string" + } + } + }, + "windows": { + "type": "object", + "additionalProperties": false, + "properties": { + "container": { + "$ref": "#/definitions/logCollectorConfigContainerProp" + }, + "filebeatYaml": { + "description": "Advanced config for LCA", + "type": "string" + } + } + } + } + }, + "container": { + "$ref": "#/definitions/logCollectorConfigContainerProp" + }, + "filebeatYaml": { + "description": "Advanced config for LCA", + "type": "string" + } + } + }, + "clustermonPod": { + "description": "configuration for clustermon pod", + "type": "object", + "additionalProperties": false, + "properties": { + "image": { + "description": "image URL of cluster collector", + "type": "string" + }, + "imagePullPolicy": { + "description": "image pull policy for cluster collector image", + "type": "string" + }, + "affinity": { + "description": "affinity for the cluster collector pod", + "type": "object" + }, + "annotations": { + "description": "annotations for the cluster collector pod.", + "type": "object" + }, + "imagePullSecrets": { + "description": "image pull secrets for cluster collector image", + "type": "array", + "items": { + "type": "object" + } + }, + "labels": { + "description": "labels for the cluster collector pod", + "type": "object" + }, + "nodeSelector": { + "description": "node selector for the cluster collector pod", + "type": "object" + }, + "priorityClassName": { + "description": "name of the pod priority class, which is used in the cluster collector pod specification to set the priority.", + "type": "string" + }, + "resources": { + "type": "object", + "description": "resources for the cluster collector pod", + "properties": { + "limits": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + }, + "requests": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + } + } + }, + "securityContext": { + "description": "security context for the cluster collector pod.", + "type": "object" + }, + "tolerations": { + "description": "tolerations for the cluster collector pod.", + "type": "array", + "items": { + "type": "object" + } + } + }, + "required": [ + "image" + ] + }, + "inframonPod": { + "description": "configuration for inframon pod", + "type": "object", + "additionalProperties": false, + "properties": { + "image": { + "description": "image URL of infra collector", + "type": "string" + }, + "imagePullPolicy": { + "description": "image pull policy for infra collector image", + "type": "string" + }, + "imagePullSecrets": { + "description": "image pull secrets for infra collector image", + "type": "array", + "items": { + "type": "object" + } + }, + "priorityClassName": { + "description": "name of the pod priority class, which is used in the infra collector pod specification to set the priority", + "type": "string" + }, + "resources": { + "description": "resources for the infra collector pod", + "type": "object", + "properties": { + "limits": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + }, + "requests": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + } + } + }, + "labels": { + "description": "labels for the infra collector pod", + "type": "object" + }, + "annotations": { + "description": "annotations for the infra collector pod", + "type": "object" + }, + "nodeSelector": { + "description": "node selector for the infra collector pod", + "type": "object" + }, + "affinity": { + "description": "affinity for the infra collector pod", + "type": "object" + }, + "tolerations": { + "description": "tolerations for the infra collector pod", + "type": "array", + "items": { + "type": "object" + } + }, + "securityContext": { + "description": "security context for the infra collector pod", + "type": "object" + }, + "env": { + "description": "override the infra collector pod configuration for a specific operating system", + "type": "object" + } + }, + "required": [ + "image" + ] + }, + "windowsExporterPod": { + "description": "configuration for windowsExporter pod", + "type": "object", + "additionalProperties": false, + "properties": { + "image": { + "description": "image URL of windows exporter", + "type": "string" + }, + "imagePullPolicy": { + "description": "image pull policy for windows exporter image", + "type": "string" + }, + "imagePullSecrets": { + "description": "image pull secrets for windows exporter image", + "type": "array", + "items": { + "type": "object" + } + }, + "priorityClassName": { + "description": "name of the pod priority class, which is used in the windows exporter pod specification to set the priority", + "type": "string" + }, + "resources": { + "description": "resources for the windows exporter pod", + "type": "object", + "properties": { + "limits": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + }, + "requests": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + } + } + }, + "labels": { + "description": "labels for the windows exporter pod", + "type": "object" + }, + "annotations": { + "description": "annotations for the windows exporter pod", + "type": "object" + }, + "nodeSelector": { + "description": "node selector for the windows exporter pod", + "type": "object" + }, + "affinity": { + "description": "affinity for the windows exporter pod", + "type": "object" + }, + "tolerations": { + "description": "tolerations for the windows exporter pod", + "type": "array", + "items": { + "type": "object" + } + }, + "securityContext": { + "description": "security context for the windows exporter pod", + "type": "object" + } + }, + "required": [ + "image" + ] + }, + "logCollectorPod": { + "description": "configuration for log collector pod", + "type": "object", + "additionalProperties": false, + "properties": { + "image": { + "description": "image URL of log collector", + "type": "string" + }, + "imagePullPolicy": { + "description": "image pull policy for log collector image", + "type": "string" + }, + "imagePullSecrets": { + "description": "image pull secrets for log collector image", + "type": "array", + "items": { + "type": "object" + } + }, + "resources": { + "description": "resources for the log collector pod", + "type": "object", + "additionalProperties": false, + "properties": { + "limits": { + "type": "object", + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + }, + "requests": { + "type": "object", + "additionalProperties": false, + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + } + } + }, + "labels": { + "description": "labels for the log collector pod", + "type": "object" + }, + "annotations": { + "description": "annotations for the log collector pod", + "type": "object" + }, + "nodeSelector": { + "description": "node selector for the log collector pod", + "type": "object" + }, + "affinity": { + "description": "affinity for the log collector pod", + "type": "object" + }, + "tolerations": { + "description": "tolerations for the log collector pod", + "type": "array", + "items": { + "type": "object" + } + }, + "securityContext": { + "description": "security context for the log collector pod", + "type": "object" + }, + "env": { + "description": "override the log collector pod configuration for a specific operating system", + "type": "object" + }, + "rollingUpdateMaxUnavailable": { + "description": "override the number of log collector pods that can be unavailable during the update process", + "type": [ + "string", + "integer" + ] + } + }, + "required": [ + "image" + ] + } + }, + "definitions": { + "logCollectorSimpleConditionProp": { + "description": "Log Collector's simple condition format (operator, key, value)", + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "type": "string" + }, + "operator": { + "enum": ["equals", "contains", "regexp", "range", "network"] + }, + "value": { + "type": "string" + } + } + }, + "logCollectorFilebeatConditionProp": { + "description": "Log Collector's condition format (follows Filebeat's autodiscover condition format)", + "type": "object", + "additionalProperties": false, + "properties": { + "equals": { + "type": "object" + }, + "contains": { + "type": "object" + }, + "regexp": { + "type": "object" + }, + "range": { + "type": "object" + }, + "network": { + "type": "object" + }, + "has_fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "or": { + "type": "array", + "items": { + "$ref": "#/definitions/logCollectorFilebeatConditionProp" + } + }, + "and": { + "type": "array", + "items": { + "$ref": "#/definitions/logCollectorFilebeatConditionProp" + } + }, + "not": { + "$ref": "#/definitions/logCollectorFilebeatConditionProp" + } + } + }, + "logCollectorConfigContainerProp": { + "description": "Log collector config for log collection from containers", + "type": "object", + "additionalProperties": false, + "properties": { + "monitorCollectors": { + "description": "Enables or disables log collection from the Log Collector and other collectors running on your cluster", + "type": [ + "boolean", + "string" + ] + }, + "defaultConfig": { + "description": "Default condition for harvesting logs from any container on your cluster", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "description": "Enable default log collection", + "type": [ + "boolean", + "string" + ] + }, + "multiLinePattern": { + "type": "string" + }, + "multiLineMatch": { + "type": "string" + }, + "multiLineNegate": { + "type": [ + "boolean", + "string" + ] + }, + "logFormat": { + "type": "string" + }, + "messageParser": { + "description": "Single-line message pattern for messages. Include only one log type in each condition block, and delete all others", + "type": "object", + "additionalProperties": false, + "properties": { + "timestamp": { + "description": "Single-line message pattern for Timestamp parser", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "format": { + "type": "string" + } + } + }, + "logback": { + "description": "Single-line message pattern for logback parser", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "pattern": { + "type": "string" + } + } + }, + "json": { + "description": "Single-line message pattern for json parser", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "timestampField": { + "type": "string" + }, + "timestampPattern": { + "type": "string" + } + } + }, + "log4J": { + "description": "Single-line message pattern for log4J parser", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "pattern": { + "type": "string" + } + } + }, + "grok": { + "description": "Single-line message pattern for grok parser", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "patterns": { + "type": "array", + "items": { + "type": "string" + } + }, + "timestampField": { + "type": "string" + }, + "timestampPattern": { + "type": "string" + } + } + }, + "infra": { + "description": "Single-line message pattern for Kubernetes infrastructure log messages", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + } + } + }, + "multi": { + "description": "Applies multiple parsers to a single log message", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "parsers": { + "type": "string" + } + } + }, + "subparsers": { + "description": "Applies subparsers to each Grok log message", + "type": "string" + } + } + } + } + }, + "conditionalConfigs": { + "description": "The block which contains all the settings for a specific log source, type, and pattern as a pair of condition+config blocks. There can be multiple condition+config pairs within conditionalConfigs", + "type": "array", + "items": { + "type": "object", + "properties": { + "condition": { + "oneOf": [ + { + "$ref": "#/definitions/logCollectorSimpleConditionProp" + }, + { + "$ref": "#/definitions/logCollectorFilebeatConditionProp" + } + ] + }, + "config": { + "type": "object", + "additionalProperties": false, + "properties": { + "logFormat": { + "type": "string" + }, + "multiLinePattern": { + "type": "string" + }, + "multiLineNegate": { + "type": [ + "boolean", + "string" + ] + }, + "multiLineMatch": { + "type": "string" + }, + "messageParser": { + "description": "Single-line message pattern for messages. Include only one log type in each condition block, and delete all others", + "type": "object", + "additionalProperties": false, + "properties": { + "timestamp": { + "description": "Single-line message pattern for Timestamp parser", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "format": { + "type": "string" + } + } + }, + "logback": { + "description": "Single-line message pattern for logback parser", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "pattern": { + "type": "string" + } + } + }, + "json": { + "description": "Single-line message pattern for json parser", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "timestampField": { + "type": "string" + }, + "timestampPattern": { + "type": "string" + } + } + }, + "log4J": { + "description": "Single-line message pattern for log4J parser", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "pattern": { + "type": "string" + } + } + }, + "grok": { + "description": "Single-line message pattern for grok parser", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "patterns": { + "type": "array", + "items": { + "type": "string" + } + }, + "timestampField": { + "type": "string" + }, + "timestampPattern": { + "type": "string" + } + } + }, + "infra": { + "description": "Single-line message pattern for Kubernetes infrastructure log messages", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + } + } + }, + "multi": { + "description": "Applies multiple parsers to a single log message", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "parsers": { + "type": "string" + } + } + }, + "subparsers": { + "description": "Applies subparsers to each Grok log message", + "type": "string" + } + } + } + } + } + } + } + }, + "excludeCondition": { + "$ref": "#/definitions/logCollectorFilebeatConditionProp" + }, + "dropFields": { + "type": "array", + "items": { + "type": "string" + } + }, + "logging": { + "type": "object", + "additionalProperties": false, + "properties": { + "level": { + "type": "string" + }, + "selectors": { + "type": "array", + "items": { + "type": "string" + } + }, + "files": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "description": "Enable logging to files", + "type": [ + "boolean", + "string" + ] + }, + "keepFiles": { + "type": "integer" + } + } + }, + "metrics": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "description": "Enable metrics logging", + "type": [ + "boolean", + "string" + ] + }, + "period": { + "type": "string" + } + } + } + } + }, + "batchSize": { + "type": "integer" + }, + "maxBytes": { + "type": "integer" + }, + "summaryDebugLogsInterval": { + "description": "Logging interval. Example: 10s.", + "type": "string" + }, + "worker": { + "description": "The number of worker threads to an output host. Default: 1. ", + "type": [ + "string", + "integer" + ] + }, + "monitoring": { + "type": "object", + "additionalProperties": false, + "properties": { + "otlpmetric": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "endpoint": { + "type": "string" + }, + "protocol": { + "enum": ["grpc", "http"] + }, + "collectPeriod": { + "type": "string" + }, + "reportPeriod": { + "type": "string" + }, + "resourceAttrs": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + }, + "metrics": { + "type": "array", + "items": { + "type": "string" + } + }, + "retry": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "initialInterval": { + "type": "string" + }, + "maxInterval": { + "type": "string" + }, + "maxElapsedTime": { + "type": "string" + } + }, + "ssl": { + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "certificateAuthorities": { + "type": "array", + "items": { + "type": "string" + } + }, + "certificate": { + "type": "string" + }, + "key": { + "type": "string" + } + } + } + } + } + } + } + } + } +} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/values.yaml new file mode 100644 index 00000000..28e48eaa --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/values.yaml @@ -0,0 +1,254 @@ +global: + smartAgentInstall: false + namespace: "" + clusterName: "" + tls: + appdCollectors: + enabled: false + secret: {} + oauth: + clientId: "" + # Either of clientSecret or clientSecretEnvVar will be present + clientSecret: "" + # clientSecretEnvVar: + # valueFrom: + # secretKeyRef: + # name: "" + # key: "" + endpoint: "" + tokenUrl: "" + agentManagementProxy: + httpProxy: "" + httpsProxy: "" + noProxy: [] + +install: + clustermon: true + defaultInfraCollectors: true + logCollector: false + +agentManagementEnabled: + clustermon: true + defaultInfraCollectors: true + logCollector: true + +# RBAC config +clustermonServiceAccount: appdynamics-clustermon +inframonServiceAccount: appdynamics-inframon +logCollectorServiceAccount: appdynamics-log-collector + +# Clustermon Configs +clustermonConfig: + os: linux + logLevel: info + logFilesMaxSizeMb: 10 + logFilesNumBackups: 4 + printToStdout: "true" + + filters: + namespace: + includeRegex: ".*" + excludeRegex: "" + entity: + excludeRegex: "" + excludeLabels: [] + label: + excludeRegex: "" + annotation: + excludeRegex: "" + scopedFilters: [] + ingressControllers: {} + + labels: + enabled: true + + events: + enabled: true + severityToExclude: [] + reasonToExclude: [] + severeGroupByReason: [] + + configurations: + enabled: true + autoscalers: + hpaVpaEnabled: true + +# Infra Manager Configs +infraManagerConfig: + logLevel: info + logFilesMaxSizeMb: 10 + logFilesNumBackups: 4 + printToStdout: "true" + +# Servermon Configs +servermonConfig: + os: [linux] + logLevel: info + logFilesMaxSizeMb: 10 + logFilesNumBackups: 4 + +# Containermon Configs +containermonConfig: + os: [linux] + logLevel: info + logFilesMaxSizeMb: 10 + logFilesNumBackups: 4 + +# LogCollector Configs +logCollectorConfig: + os: [linux] + container: + monitorCollectors: false + defaultConfig: + enabled: true + conditionalConfigs: [] + dropFields: [] + batchSize: 1000 + worker: 1 + maxBytes: 1000000 + summaryDebugLogsInterval: 10s + logging: + level: info + selectors: [] + files: + enabled: false + keepFiles: 5 + metrics: + enabled: false + period: 30s + monitoring: + otlpmetric: + enabled: false + endpoint: "${APPD_OTELCOL_GRPC_RECEIVER_HOST}:${APPD_OTELCOL_GRPC_RECEIVER_PORT}" + protocol: grpc + resourceAttrs: [] + # default metrics to capture + metrics: + - beat.memstats.memory_alloc + - filebeat.events.active + - libbeat.output.read.errors + - libbeat.output.write.bytes + - libbeat.output.write.errors + - system.load.norm.5 + - system.load.norm.15 + - filebeat.input.filestream.harvester.running + - filebeat.input.filestream.harvester.stopped + - filebeat.input.filestream.files.open + - filebeat.input.filestream.events.eof + - filebeat.input.filestream.events.write + - filebeat.input.filestream.events.create + - filebeat.input.filestream.events.rename + - filebeat.input.filestream.events.delete + - filebeat.input.filestream.events.truncate + retry: + enabled: false + ssl: + enabled: false + certificateAuthorities: [] + filebeatYaml: "" + env: + linux: + filebeatYaml: "" + windows: + filebeatYaml: "" + +# Deployment specific configs +clustermonPod: + image: appdynamics/appdynamics-cloud-k8s-monitoring:24.4.0-2034 + imagePullPolicy: Always + resources: + limits: + cpu: 1000m + memory: 1000Mi + requests: + cpu: 500m + memory: 750Mi + labels: {} + annotations: {} + nodeSelector: {} + imagePullSecrets: [] + affinity: {} + tolerations: [] + securityContext: {} + +# Daemonset specific configs +inframonPod: + image: appdynamics/appdynamics-cloud-k8s-monitoring:24.4.0-2034 + imagePullPolicy: Always + resources: + limits: + cpu: 350m + memory: 100Mi + requests: + cpu: 200m + memory: 64Mi + labels: {} + annotations: {} + nodeSelector: {} + imagePullSecrets: [] + affinity: {} + tolerations: [] + securityContext: {} + env: + linux: + nodeSelector: + kubernetes.io/os: linux + windows: + resources: + limits: + cpu: 350m + memory: 300Mi + requests: + cpu: 200m + memory: 150Mi + nodeSelector: + kubernetes.io/os: windows + +windowsExporterPod: + image: ghcr.io/prometheus-community/windows-exporter:0.24.0 + imagePullPolicy: Always + resources: + limits: + cpu: 200m + memory: 200Mi + requests: + cpu: 100m + memory: 100Mi + labels: {} + annotations: {} + nodeSelector: {} + imagePullSecrets: [] + affinity: {} + tolerations: [] + securityContext: {} + +# Daemonset specific configs +logCollectorPod: + image: appdynamics/appdynamics-cloud-log-collector-agent:24.4.0-1163 + imagePullPolicy: Always + resources: + limits: + cpu: 400m + memory: 512Mi + requests: + cpu: 10m + memory: 150Mi + labels: {} + annotations: {} + nodeSelector: {} + imagePullSecrets: [] + affinity: {} + tolerations: [] + securityContext: {} + # MaxUnavailable replicas for Daemonset rolling update. This can be both absolute value(int) or in percentage. + rollingUpdateMaxUnavailable: 100% + env: + linux: + nodeSelector: + kubernetes.io/os: linux + windows: + nodeSelector: + kubernetes.io/os: windows + + + diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/.helmignore b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/.helmignore new file mode 100644 index 00000000..88b6008a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/.helmignore @@ -0,0 +1,25 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +# CA bundle asc files +*.asc diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/Chart.lock b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/Chart.lock new file mode 100644 index 00000000..0ea0e6ac --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: metrics-server + repository: https://kubernetes-sigs.github.io/metrics-server/ + version: 3.7.0 +digest: sha256:284524138c4288858ee1e1a748625f9de5f8e374b99a370c2a64671b260325e1 +generated: "2024-04-26T06:32:18.441913724Z" diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/Chart.yaml new file mode 100644 index 00000000..76317229 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/Chart.yaml @@ -0,0 +1,25 @@ +apiVersion: v2 +appVersion: 24.1.0 +dependencies: +- condition: install.metrics-server + name: metrics-server + repository: https://kubernetes-sigs.github.io/metrics-server/ + version: 3.7.0 +description: Sophisticated helm chart to deploy cluster agent and machine agent in + addition with advanced features like multiple cluster agent deployments, Granular + control over config with intuitive boolean switches +home: https://appdynamics.com +icon: https://raw.githubusercontent.com/CiscoDevNet/appdynamics-charts/master/logo.png +keywords: +- appdynamics +- cluster +- kubernetes +- openshift +- monitoring +- pod +- deployment +maintainers: +- email: support@appdynamics.com + name: AppDynamics +name: appdynamics-csaas-k8s-cluster-agent +version: 1.19.0 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/README.md b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/README.md new file mode 100644 index 00000000..da3d424d --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/README.md @@ -0,0 +1,37 @@ +# Appdynamics Helm Chart + +### Add AppDynamics helm repo + +### Create values yaml to override default ones +```yaml +installClusterAgent: true +installInfraViz: false + +imageInfo: + agentImage: docker.io/appdynamics/cluster-agent + agentTag: 22.1.0 # Will be used for operator pod + machineAgentImage: docker.io/appdynamics/machine-agent + machineAgentTag: latest + machineAgentWinImage: docker.io/appdynamics/machine-agent-analytics + machineAgentWinTag: win-latest + netVizImage: docker.io/appdynamics/machine-agent-netviz + netvizTag: latest + +controllerInfo: + url: + account: + username: + password: + accessKey: + globalAccount: # To be provided when using machineAgent Window Image + +agentServiceAccount: appdynamics-cluster-agent +infravizServiceAccount: appdynamics-infraviz +``` +### Install cluster agent or machine agent using helm chart +```bash +helm install cluster-agent appdynamics-charts/cluster-agent -f .yaml --namespace appdynamics +``` + +### Note: +cluster agent installation is independent of otel collector. \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/.helmignore b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/Chart.yaml new file mode 100644 index 00000000..0413ef0a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/Chart.yaml @@ -0,0 +1,26 @@ +annotations: + artifacthub.io/changes: | + - kind: changed + description: "Update Metrics Server image to v0.5.2." +apiVersion: v2 +appVersion: 0.5.2 +description: Metrics Server is a scalable, efficient source of container resource + metrics for Kubernetes built-in autoscaling pipelines. +home: https://github.com/kubernetes-sigs/metrics-server +icon: https://avatars.githubusercontent.com/u/36015203?s=400&v=4 +keywords: +- kubernetes +- metrics-server +- metrics +maintainers: +- name: stevehipwell + url: https://github.com/stevehipwell +- name: krmichel + url: https://github.com/krmichel +- name: endrec + url: https://github.com/endrec +name: metrics-server +sources: +- https://github.com/kubernetes-sigs/metrics-server +type: application +version: 3.7.0 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/README.md b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/README.md new file mode 100644 index 00000000..51817069 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/README.md @@ -0,0 +1,64 @@ +# Kubernetes Metrics Server + +[Metrics Server](https://github.com/kubernetes-sigs/metrics-server/) is a scalable, efficient source of container resource metrics for Kubernetes built-in autoscaling pipelines. + + + +## Installing the Chart + +Before you can install the chart you will need to add the `metrics-server` repo to [Helm](https://helm.sh/). + +```shell +helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/ +``` + +After you've installed the repo you can install the chart. + +```shell +helm upgrade --install metrics-server metrics-server/metrics-server +``` + +## Configuration + +The following table lists the configurable parameters of the _Metrics Server_ chart and their default values. + +| Parameter | Description | Default | +| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | +| `image.repository` | Image repository. | `k8s.gcr.io/metrics-server/metrics-server` | +| `image.tag` | Image tag, will override the default tag derived from the chart app version. | `""` | +| `image.pullPolicy` | Image pull policy. | `IfNotPresent` | +| `imagePullSecrets` | Image pull secrets. | `[]` | +| `nameOverride` | Override the `name` of the chart. | `nil` | +| `fullnameOverride` | Override the `fullname` of the chart. | `nil` | +| `serviceAccount.create` | If `true`, create a new service account. | `true` | +| `serviceAccount.annotations` | Annotations to add to the service account. | `{}` | +| `serviceAccount.name` | Service account to be used. If not set and `serviceAccount.create` is `true`, a name is generated using the full name template. | `nil` | +| `rbac.create` | If `true`, create the RBAC resources. | `true` | +| `rbac.pspEnabled` | If `true`, create a pod security policy resource. | `false` | +| `apiService.create` | If `true`, create the `v1beta1.metrics.k8s.io` API service. You typically want this enabled! If you disable API service creation you have to manage it outside of this chart for e.g horizontal pod autoscaling to work with this release. | `true` | +| `podLabels` | Labels to add to the pod. | `{}` | +| `podAnnotations` | Annotations to add to the pod. | `{}` | +| `podSecurityContext` | Security context for the pod. | `{}` | +| `securityContext` | Security context for the _metrics-server_ container. | _See values.yaml_ | +| `priorityClassName` | Priority class name to use. | `system-cluster-critical` | +| `containerPort` | port for the _metrics-server_ container. | `4443` | +| `hostNetwork.enabled` | If `true`, start _metric-server_ in hostNetwork mode. You would require this enabled if you use alternate overlay networking for pods and API server unable to communicate with metrics-server. As an example, this is required if you use Weave network on EKS. | `false` | +| `replicas` | Number of replicas to run. | `1` | +| `updateStrategy` | Customise the default update strategy. | `{}` | +| `podDisruptionBudget.enabled` | If `true`, create `PodDisruptionBudget` resource. | `{}` | +| `podDisruptionBudget.minAvailable` | Set the `PodDisruptionBugdet` minimum available pods. | `nil` | +| `podDisruptionBudget.maxUnavailable` | Set the `PodDisruptionBugdet` maximum unavailable pods. | `nil` | +| `defaultArgs` | Default arguments to pass to the _metrics-server_ command. | See _values.yaml_ | +| `args` | Additional arguments to pass to the _metrics-server_ command. | `[]` | +| `livenessProbe` | Liveness probe. | See _values.yaml_ | +| `readinessProbe` | Readiness probe. | See _values.yaml_ | +| `service.type` | Service type. | `ClusterIP` | +| `service.port` | Service port. | `443` | +| `service.annotations` | Annotations to add to the service. | `{}` | +| `service.labels` | Labels to add to the service. | `{}` | +| `resources` | Resource requests and limits for the _metrics-server_ container. | `{}` | +| `extraVolumeMounts` | Additional volume mounts for the _metrics-server_ container. | `[]` | +| `extraVolumes` | Additional volumes for the pod. | `[]` | +| `nodeSelector` | Node labels for pod assignment. | `{}` | +| `tolerations` | Tolerations for pod assignment. | `[]` | +| `affinity` | Affinity for pod assignment. | `{}` | diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/ci/ci-values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/ci/ci-values.yaml new file mode 100644 index 00000000..b9e9ef73 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/ci/ci-values.yaml @@ -0,0 +1,2 @@ +args: + - --kubelet-insecure-tls diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/NOTES.txt b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/NOTES.txt new file mode 100644 index 00000000..0ad6bb07 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/NOTES.txt @@ -0,0 +1,7 @@ +*********************************************************************** +* Metrics Server * +*********************************************************************** + Chart version: {{ .Chart.Version }} + App version: {{ .Chart.AppVersion }} + Image tag: {{ include "metrics-server.image" . }} +*********************************************************************** diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/_helpers.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/_helpers.tpl new file mode 100644 index 00000000..f5581697 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/_helpers.tpl @@ -0,0 +1,78 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "metrics-server.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "metrics-server.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "metrics-server.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "metrics-server.labels" -}} +helm.sh/chart: {{ include "metrics-server.chart" . }} +{{ include "metrics-server.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "metrics-server.selectorLabels" -}} +app.kubernetes.io/name: {{ include "metrics-server.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "metrics-server.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "metrics-server.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +The image to use +*/}} +{{- define "metrics-server.image" -}} +{{- printf "%s:%s" .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }} +{{- end }} + +{{/* Get PodDisruptionBudget API Version */}} +{{- define "metrics-server.pdb.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "policy/v1") (semverCompare ">= 1.21-0" .Capabilities.KubeVersion.Version) -}} + {{- print "policy/v1" -}} + {{- else -}} + {{- print "policy/v1beta1" -}} + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/apiservice.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/apiservice.yaml new file mode 100644 index 00000000..dd37b5db --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/apiservice.yaml @@ -0,0 +1,17 @@ +{{- if .Values.apiService.create -}} +apiVersion: apiregistration.k8s.io/v1 +kind: APIService +metadata: + name: v1beta1.metrics.k8s.io + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +spec: + group: metrics.k8s.io + groupPriorityMinimum: 100 + insecureSkipTLSVerify: true + service: + name: {{ include "metrics-server.fullname" . }} + namespace: {{ .Release.Namespace }} + version: v1beta1 + versionPriority: 100 +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrole-aggregated-reader.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrole-aggregated-reader.yaml new file mode 100644 index 00000000..d5e8fe1b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrole-aggregated-reader.yaml @@ -0,0 +1,21 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ printf "system:%s-aggregated-reader" (include "metrics-server.name" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-view: "true" +rules: + - apiGroups: + - metrics.k8s.io + resources: + - pods + - nodes + verbs: + - get + - list + - watch +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrole.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrole.yaml new file mode 100644 index 00000000..0636414f --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrole.yaml @@ -0,0 +1,32 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ printf "system:%s" (include "metrics-server.fullname" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - pods + - nodes + - nodes/stats + - namespaces + - configmaps + verbs: + - get + - list + - watch + {{- if .Values.rbac.pspEnabled }} + - apiGroups: + - extensions + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ printf "privileged-%s" (include "metrics-server.fullname" .) }} + verbs: + - use + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrolebinding-auth-delegator.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrolebinding-auth-delegator.yaml new file mode 100644 index 00000000..826c3b7b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrolebinding-auth-delegator.yaml @@ -0,0 +1,16 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ printf "%s:system:auth-delegator" (include "metrics-server.fullname" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: + - kind: ServiceAccount + name: {{ include "metrics-server.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..512cb651 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ printf "system:%s" (include "metrics-server.fullname" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:{{ template "metrics-server.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "metrics-server.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/deployment.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/deployment.yaml new file mode 100644 index 00000000..c8ca76b4 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/deployment.yaml @@ -0,0 +1,94 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "metrics-server.fullname" . }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicas }} + {{- with .Values.updateStrategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "metrics-server.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "metrics-server.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "metrics-server.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + {{- if .Values.hostNetwork.enabled }} + hostNetwork: true + {{- end }} + containers: + - name: metrics-server + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: {{ include "metrics-server.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - {{ printf "--secure-port=%d" (int .Values.containerPort) }} + {{- range .Values.defaultArgs }} + - {{ . }} + {{- end }} + {{- range .Values.args }} + - {{ . }} + {{- end }} + ports: + - name: https + protocol: TCP + containerPort: {{ .Values.containerPort }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + volumeMounts: + - name: tmp + mountPath: /tmp + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: tmp + emptyDir: {} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/pdb.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/pdb.yaml new file mode 100644 index 00000000..1320b207 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/pdb.yaml @@ -0,0 +1,18 @@ +{{- if .Values.podDisruptionBudget.enabled -}} +apiVersion: {{ include "metrics-server.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "metrics-server.fullname" . }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +spec: + {{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "metrics-server.selectorLabels" . | nindent 6 }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/psp.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/psp.yaml new file mode 100644 index 00000000..bf8ace1a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/psp.yaml @@ -0,0 +1,28 @@ +{{- if .Values.rbac.pspEnabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ printf "privileged-%s" (include "metrics-server.fullname" .) }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +spec: + allowedCapabilities: + - '*' + fsGroup: + rule: RunAsAny + privileged: true + runAsUser: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + volumes: + - '*' + hostPID: true + hostIPC: true + hostNetwork: true + hostPorts: + - min: 1 + max: 65536 +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/rolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/rolebinding.yaml new file mode 100644 index 00000000..3fda7433 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ printf "%s-auth-reader" (include "metrics-server.fullname" .) }} + namespace: kube-system + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: {{ include "metrics-server.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/service.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/service.yaml new file mode 100644 index 00000000..7470218f --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/service.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "metrics-server.fullname" . }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} + {{- with .Values.service.labels -}} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - name: https + port: {{ .Values.service.port }} + protocol: TCP + targetPort: https + selector: + {{- include "metrics-server.selectorLabels" . | nindent 4 }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/serviceaccount.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/serviceaccount.yaml new file mode 100644 index 00000000..12f77245 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "metrics-server.serviceAccountName" . }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "metrics-server.labels" . | nindent 4 }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/values.yaml new file mode 100644 index 00000000..0504399d --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/values.yaml @@ -0,0 +1,121 @@ +# Default values for metrics-server. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +image: + repository: k8s.gcr.io/metrics-server/metrics-server + # Overrides the image tag whose default is v{{ .Chart.AppVersion }} + tag: "" + pullPolicy: IfNotPresent + +imagePullSecrets: [] +# - registrySecretName + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +rbac: + # Specifies whether RBAC resources should be created + create: true + pspEnabled: false + +apiService: + # Specifies if the v1beta1.metrics.k8s.io API service should be created. + # + # You typically want this enabled! If you disable API service creation you have to + # manage it outside of this chart for e.g horizontal pod autoscaling to + # work with this release. + create: true + +podLabels: {} +podAnnotations: {} + +podSecurityContext: {} + +securityContext: + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + allowPrivilegeEscalation: false + +priorityClassName: system-cluster-critical + +containerPort: 4443 + +hostNetwork: + # Specifies if metrics-server should be started in hostNetwork mode. + # + # You would require this enabled if you use alternate overlay networking for pods and + # API server unable to communicate with metrics-server. As an example, this is required + # if you use Weave network on EKS + enabled: false + +replicas: 1 + +updateStrategy: {} +# type: RollingUpdate +# rollingUpdate: +# maxSurge: 0 +# maxUnavailable: 1 + +podDisruptionBudget: + # https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + enabled: false + minAvailable: + maxUnavailable: + +defaultArgs: + - --cert-dir=/tmp + - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname + - --kubelet-use-node-status-port + - --metric-resolution=15s + +args: [] + +livenessProbe: + httpGet: + path: /livez + port: https + scheme: HTTPS + initialDelaySeconds: 0 + periodSeconds: 10 + failureThreshold: 3 + +readinessProbe: + httpGet: + path: /readyz + port: https + scheme: HTTPS + initialDelaySeconds: 20 + periodSeconds: 10 + failureThreshold: 3 + +service: + type: ClusterIP + port: 443 + annotations: {} + labels: {} + # Add these labels to have metrics-server show up in `kubectl cluster-info` + # kubernetes.io/cluster-service: "true" + # kubernetes.io/name: "Metrics-server" + +resources: {} + +extraVolumeMounts: [] + +extraVolumes: [] + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/NOTES.txt b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/NOTES.txt new file mode 100644 index 00000000..5a0bd120 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/NOTES.txt @@ -0,0 +1,15 @@ +Check HELM release status: + + $ helm status {{ .Release.Name }} -n {{ .Release.Namespace }} + $ helm get {{ .Release.Name }} -n {{ .Release.Namespace }} + +List cluster agent and machine agent pods: + + $ kubectl get pods -n {{ .Release.Namespace }} + +Release state: + Install ClusterAgent: {{ .Values.installClusterAgent }} + Install InfraViz: {{ .Values.installInfraViz }} + Controller URL: {{ .Values.controllerInfo.url }} + Auto-Instrumentation enabled: {{ .Values.instrumentationConfig.enabled }} + Installing metrics-server: {{ get .Values.install "metrics-server" }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/_helper.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/_helper.tpl new file mode 100644 index 00000000..26fc504d --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/_helper.tpl @@ -0,0 +1,5 @@ +{{- define "appdynamics-csaas-k8s-cluster-agent.sensitiveData" -}} +{{- if (get . "data") | required (get . "message") -}} +{{ (get . "data") | trim | b64enc }} +{{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/cluster-agent.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/cluster-agent.yaml new file mode 100644 index 00000000..3cc54563 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/cluster-agent.yaml @@ -0,0 +1,228 @@ +{{ if .Values.installClusterAgent -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: Clusteragent +metadata: + name: {{ (cat (regexReplaceAll "([^a-zA-Z0-9-.]+)" (lower (.Values.clusterAgent.appName | default (cat .Release.Name "-" "appdynamics-cluster-agent" | nospace))) "-") "-" .Release.Namespace | nospace) | trunc 63 }} + namespace: {{ .Release.Namespace }} +spec: + appName: {{ (cat (.Values.global.clusterName | default (cat .Release.Name "-" "appdynamics-cluster-agent" | nospace)) "-" .Release.Namespace | nospace) | trunc 63 }} + controllerUrl: {{ required "AppDynamics controller URL is required!" .Values.controllerInfo.url }} + account: {{ required "AppDynamics controller account is required!" .Values.controllerInfo.account }} + image: {{ .Values.imageInfo.agentImage }}:{{ .Values.imageInfo.agentTag }} + serviceAccountName: {{ .Values.agentServiceAccount }} + + {{ if .Values.controllerInfo.customSSLCert -}} + # Custom SSL config + customSSLSecret: cluster-agent-ssl-cert + {{- end }} + + {{ with .Values.controllerInfo -}} + {{ if .proxyUrl -}} + # Proxy config + proxyUrl: {{ .proxyUrl }} + {{ if .authenticateProxy -}} + proxyUser: {{ required "Proxy user is required to authenticate proxy!" .proxyUser }} + {{- end }} + {{- end }} + {{- end }} + + # Ad-Hoc properties + {{ with .Values.clusterAgent -}} + nsToMonitor: + {{- toYaml .nsToMonitor | nindent 4 }} + {{ if .nsToMonitorRegex -}} + nsToMonitorRegex: {{ .nsToMonitorRegex }} + {{- end }} + {{ if .nsToExcludeRegex -}} + nsToExcludeRegex: {{ .nsToExcludeRegex }} + {{- end }} + clusterMetricsSyncInterval: {{ .clusterMetricsSyncInterval }} + metadataSyncInterval: {{ .metadataSyncInterval }} + eventUploadInterval: {{ .eventUploadInterval }} + httpClientTimeout: {{ .httpClientTimeout }} + podBatchSize: {{ .podBatchSize }} + instrumentationMaxPollingAttempts: {{ .instrumentationMaxPollingAttempts }} + instrumentationNsStatusPollingIntervalMinutes: {{ .instrumentationNsStatusPollingIntervalMinutes }} + priorityClassName: {{ .priorityClassName }} + # Container specific properties + {{ with .containerProperties -}} + containerBatchSize: {{ .containerBatchSize }} + #containerParallelRequestLimit: {{ .containerParallelRequestLimit }} + containerRegistrationInterval: {{ .containerRegistrationInterval }} + {{- end }} + + # Metric specific properties + {{ with .metricProperties -}} + metricsSyncInterval: {{ .metricsSyncInterval }} + metricUploadRetryCount: {{ .metricUploadRetryCount }} + metricUploadRetryIntervalMilliSeconds: {{ .metricUploadRetryIntervalMilliSeconds }} + {{- end }} + + # Log specific properties + {{ with .logProperties -}} + logFileSizeMb: {{ .logFileSizeMb }} + logFileBackups: {{ .logFileBackups }} + logLevel: {{ .logLevel }} + {{- end }} + + {{ if .memoryThresholdForRestart -}} + # Cluster Agent memory threshold for restart + memoryThresholdForRestart: {{ .memoryThresholdForRestart }} + {{- end }} + + {{ if .enableClusterAgentRestartProbe -}} + # Cluster Agent graceful restart prob + enableClusterAgentRestartProbe: {{ .enableClusterAgentRestartProbe }} + {{- end }} + + {{ if .imagePullPolicy -}} + # Cluster Agent Image pull policy + imagePullPolicy: {{ .imagePullPolicy }} + {{- end }} + + {{ if .imagePullSecret -}} + # Image pull secret + imagePullSecret: {{ .imagePullSecret }} + {{- end }} + {{- end }} + + # profiling specific properties + {{ with .Values.agentProfiler -}} + pprofEnabled: {{ .pprofEnabled }} + pprofPort: {{ .pprofPort }} + {{- end }} + # Pod filter properties + podFilter: + {{- toYaml .Values.podFilter | nindent 4 }} + + # Node selector + nodeSelector: + {{- toYaml .Values.agentPod.nodeSelector | nindent 4 }} + + # Tolerations + tolerations: + {{- toYaml .Values.agentPod.tolerations | nindent 4 }} + + labels: + {{- toYaml .Values.agentPod.labels | nindent 4 }} + + # Resources + resources: + {{- toYaml .Values.agentPod.resources | nindent 4 }} + + {{ with .Values.instrumentationConfig -}} + {{ if .enabled -}} + # Instrumentation config + {{ if .defaultAppName -}} + defaultAppName: {{ .defaultAppName }} + {{- end }} + {{ if .defaultEnv -}} + defaultEnv: {{ .defaultEnv }} + {{- end }} + {{ if .defaultInstrumentationLabelMatch -}} + defaultInstrumentationLabelMatch: + {{- toYaml .defaultInstrumentationLabelMatch | nindent 4 }} + {{- end }} + {{ if .defaultInstrumentMatchString -}} + defaultInstrumentMatchString: {{ .defaultInstrumentMatchString }} + {{- end }} + {{ if .defaultCustomConfig -}} + defaultCustomConfig: {{ .defaultCustomConfig }} + {{- end }} + {{ if .appNameStrategy -}} + appNameStrategy: {{ .appNameStrategy }} + {{- end }} + {{ if .tierNameStrategy -}} + tierNameStrategy: {{ .tierNameStrategy }} + {{- end }} + {{ if .appNameLabel -}} + appNameLabel: {{ .appNameLabel }} + {{- end }} + {{ if .tierNameLabel -}} + tierNameLabel: {{ .tierNameLabel }} + {{- end }} + {{ if .nodeName -}} + nodeName: {{ .nodeName }} + {{- end }} + {{ if .imageInfo -}} + imageInfo: + {{- toYaml .imageInfo | nindent 4}} + {{- end }} + {{ if .instrumentationMethod -}} + instrumentationMethod: {{ .instrumentationMethod }} + {{- end }} + {{ if .resourcesToInstrument -}} + resourcesToInstrument: + {{- toYaml .resourcesToInstrument | nindent 4 }} + {{- end }} + {{ if .instrumentationRules -}} + instrumentationRules: + {{- toYaml .instrumentationRules | nindent 4 }} + {{- end }} + {{ if .nsToInstrumentRegex -}} + nsToInstrumentRegex: {{ .nsToInstrumentRegex }} + {{- end }} + {{ if .netvizInfo -}} + netvizInfo: + {{- toYaml .netvizInfo | nindent 4 }} + {{- end }} + {{ if .runAsUser -}} + runAsUser: {{ .runAsUser }} + {{- end }} + {{ if .runAsGroup -}} + runAsGroup: {{ .runAsGroup }} + {{- end }} + {{ if .runAsNonRoot -}} + runAsNonRoot: {{ .runAsNonRoot }} + {{- end }} + {{ if .readOnlyRootFilesystem -}} + readOnlyRootFilesystem: {{ .readOnlyRootFilesystem }} + {{- end }} + {{ if .allowPrivilegeEscalation -}} + allowPrivilegeEscalation: {{ .allowPrivilegeEscalation }} + {{- end }} + {{ if .capabilities -}} + capabilities: {{ .capabilities }} + {{- end }} + {{ if .seccompProfile -}} + seccompProfile: {{ .seccompProfile }} + {{- end }} + {{ if .windowsOptions -}} + windowsOptions: {{ .windowsOptions }} + {{- end }} + {{ if .seLinuxOptions -}} + seLinuxOptions: {{ .seLinuxOptions }} + {{- end }} + {{ if .procMount -}} + procMount: {{ .procMount }} + {{- end }} + {{ if .privileged -}} + privileged: {{ .privileged }} + {{- end }} + {{ if .numberOfTaskWorkers -}} + numberOfTaskWorkers: {{ .numberOfTaskWorkers }} + {{- end }} + {{ if .defaultAnalyticsHost -}} + defaultAnalyticsHost: {{ .defaultAnalyticsHost }} + {{- end }} + {{ if .defaultAnalyticsPort -}} + defaultAnalyticsPort: {{ .defaultAnalyticsPort }} + {{- end }} + {{ if .defaultAnalyticsSslEnabled -}} + defaultAnalyticsSslEnabled: {{ .defaultAnalyticsSslEnabled }} + {{- end }} + {{ if .enableInstallationReport -}} + enableInstallationReport: {{ .enableInstallationReport }} + {{ end -}} + {{ if .enableForceReInstrumentation -}} + enableForceReInstrumentation: {{ .enableForceReInstrumentation }} + {{ end -}} + {{if .containerAppCorrelationMethod -}} + containerAppCorrelationMethod: {{ .containerAppCorrelationMethod }} + {{ end -}} + {{if .metadataServerPort -}} + metadataServerPort: {{ .metadataServerPort }} + {{ end -}} + {{ end -}} + {{ end -}} +{{ end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/infraviz.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/infraviz.yaml new file mode 100644 index 00000000..392d3c2c --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/infraviz.yaml @@ -0,0 +1,120 @@ +{{ if .Values.installInfraViz -}} +apiVersion: cluster.appdynamics.com/v1alpha1 +kind: InfraViz +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-infraviz" | trunc 63 }} + namespace: {{ .Release.Namespace }} +spec: + controllerUrl: {{ required "AppDynamics controller URL is required!" .Values.controllerInfo.url }} + account: {{ required "AppDynamics controller account is required!" .Values.controllerInfo.account }} + + {{ if .Values.controllerInfo.keyStoreFileSecret -}} + # Custom SSL config + keyStoreFileSecret: {{ .Values.controllerInfo.keyStoreFileSecret }} + keystorePasswordSecret: {{ .Values.controllerInfo.keystorePasswordSecret }} + {{- end }} + + {{- if eq .Values.infraViz.nodeOS "linux" }} + image: {{ .Values.imageInfo.machineAgentImage }}:{{ .Values.imageInfo.machineAgentTag }} + globalAccount: {{ required "AppDynamics controller global account is required when using machine-agent linux image!" .Values.controllerInfo.globalAccount }} + {{- else if eq .Values.infraViz.nodeOS "windows" }} + imageWin: {{ .Values.imageInfo.machineAgentWinImage }}:{{ .Values.imageInfo.machineAgentWinTag }} + globalAccount: {{ required "AppDynamics controller global account is required when using machine-agent win image!" .Values.controllerInfo.globalAccount }} + {{- else if eq .Values.infraViz.nodeOS "all" }} + image: {{ .Values.imageInfo.machineAgentImage }}:{{ .Values.imageInfo.machineAgentTag }} + imageWin: {{ .Values.imageInfo.machineAgentWinImage }}:{{ .Values.imageInfo.machineAgentWinTag }} + globalAccount: {{ required "AppDynamics controller global account is required when using machine-agent win image!" .Values.controllerInfo.globalAccount }} + {{- end }} + + {{ with .Values.controllerInfo -}} + {{ if .proxyUrl -}} + # Proxy config + proxyUrl: {{ .proxyUrl }} + {{ if .authenticateProxy -}} + proxyUser: {{ required "Proxy user is required to authenticate proxy!" .proxyUser }} + {{- end }} + {{- end }} + {{- end }} + + + {{ with .Values.infraViz -}} + nodeOS: {{ .nodeOS -}} + {{ if .enableMasters }} + enableMasters: {{ .enableMasters -}} + {{- end }} + {{ if .stdoutLogging -}} + stdoutLogging: {{ .stdoutLogging -}} + {{- end }} + {{ if .enableContainerHostId -}} + enableContainerHostId: {{ .enableContainerHostId -}} + {{- end }} + {{ if .runAsUser -}} + runAsUser: {{ .runAsUser -}} + {{- end }} + {{ if .runAsGroup -}} + runAsGroup: {{ .runAsGroup -}} + {{- end }} + {{ if .fsGroup -}} + fsGroup: {{ .fsGroup -}} + {{- end }} + {{ if .enableServerViz -}} + enableServerViz: {{ .enableServerViz -}} + {{- end }} + {{ if .enableDockerViz -}} + enableDockerViz: {{ .enableDockerViz -}} + {{- end }} + {{ if .eventServiceUrl -}} + eventServiceUrl: {{ .eventServiceUrl -}} + {{- end }} + + # Log specific properties + {{ with .logProperties -}} + logLevel: {{ .logLevel }} + {{- end }} + + {{ with .metricProperties -}} + metricsLimit: {{ .metricsLimit | quote -}} + {{- end }} + + {{ if .propertyBag -}} + propertyBag: {{ .propertyBag -}} + {{- end }} + + {{ if .uniqueHostId -}} + uniqueHostId: {{ .uniqueHostId -}} + {{- end }} + + {{- end }} + + {{ if .Values.netViz.enabled -}} + netVizImage: {{ .Values.imageInfo.netVizImage }}:{{ .Values.imageInfo.netvizTag }} + netVizPort: {{ .Values.netViz.netVizPort -}} + {{- end}} + {{ if .Values.infravizPod.imagePullSecret -}} + imagePullSecret: {{ .Values.infravizPod.imagePullSecret }} + {{- end }} + {{ if .Values.infravizPod.imagePullPolicy -}} + imagePullPolicy: {{ .Values.infravizPod.imagePullPolicy }} + {{- end }} + nodeSelector: + {{- toYaml .Values.infravizPod.nodeSelector | nindent 6 }} + priorityClassName: + {{- toYaml .Values.infravizPod.priorityClassName | nindent 6 }} + # Tolerations + tolerations: + {{- toYaml .Values.infravizPod.tolerations | nindent 6 }} + # Resources + resources: + {{- toYaml .Values.infravizPod.resources | nindent 6 }} + {{ if .Values.infravizPod.overrideVolumeMounts -}} + overrideVolumeMounts: + {{- toYaml .Values.infravizPod.overrideVolumeMounts | nindent 6 }} + {{ end -}} + {{ if .Values.infravizPod.env -}} + env: + {{- toYaml .Values.infravizPod.env | nindent 6 }} + {{ end -}} + #netviz resources + resourcesNetViz: + {{- toYaml .Values.netViz.resourcesNetViz | nindent 6 }} +{{ end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/cr-agent-generic.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/cr-agent-generic.yaml new file mode 100644 index 00000000..d0470b17 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/cr-agent-generic.yaml @@ -0,0 +1,73 @@ +{{ if .Values.installClusterAgent -}} +{{ $releaseName := .Release.Name}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: appdynamics-cluster-agent-{{.Release.Name}} +rules: +- apiGroups: + - "" + resources: + - pods + - pods/log + - endpoints + - persistentvolumeclaims + - resourcequotas + - nodes + - events + - services + - configmaps + - secrets + - replicationcontrollers + verbs: + - get + - watch + - list +- apiGroups: + - apps + resources: + - daemonsets + - statefulsets + - deployments + - replicasets + verbs: + - get + - watch + - list +- apiGroups: + - "batch" + - "extensions" + resources: + - "jobs" + verbs: + - "get" + - "list" + - "watch" +- apiGroups: + - metrics.k8s.io + resources: + - pods + - nodes + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - update + - list +{{ if .Capabilities.APIVersions.Has "apps.openshift.io/v1/DeploymentConfig" -}} +- apiGroups: + - apps.openshift.io + resources: + - deploymentconfigs + verbs: + - get + - watch + - list +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/cr-agent-instrumentation.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/cr-agent-instrumentation.yaml new file mode 100644 index 00000000..a9e2dfe7 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/cr-agent-instrumentation.yaml @@ -0,0 +1,66 @@ +{{ if .Values.installClusterAgent -}} +{{ $releaseName := .Release.Name}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: appdynamics-cluster-agent-instrumentation-{{.Release.Name}} +rules: +- apiGroups: + - "" + resources: + - pods + - pods/exec + - secrets + - configmaps + verbs: + - create + - update + - delete +- apiGroups: + - apps + resources: + - daemonsets + - statefulsets + - deployments + - replicasets + verbs: + - update +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - update + - list +{{ if .Capabilities.APIVersions.Has "apps.openshift.io/v1/DeploymentConfig" -}} +- apiGroups: + - apps.openshift.io + resources: + - deploymentconfigs + verbs: + - update +{{- end }} +{{ with .containerAppCorrelationMethod }} +{{ if eq . "kubeapi" }} +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - create + - delete +- apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + - rolebindings + verbs: + - get + - create + - update + - delete +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/crb-agent-generic.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/crb-agent-generic.yaml new file mode 100644 index 00000000..a258183b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/crb-agent-generic.yaml @@ -0,0 +1,16 @@ +{{ if .Values.installClusterAgent -}} +{{ $agentSA := .Values.agentServiceAccount }} +{{ $namespace := .Release.Namespace }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-cluster-agent" }} +subjects: +{{ printf "- kind: ServiceAccount" | nindent 2 }} +{{ printf "name: %s" $agentSA | nindent 4 }} +{{ printf "namespace: %s" $namespace | nindent 4}} +roleRef: + kind: ClusterRole + name: appdynamics-cluster-agent-{{.Release.Name}} + apiGroup: rbac.authorization.k8s.io +{{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/crb-agent-instrumentation.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/crb-agent-instrumentation.yaml new file mode 100644 index 00000000..6d703554 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/crb-agent-instrumentation.yaml @@ -0,0 +1,16 @@ +{{ if .Values.installClusterAgent -}} +{{ $agentSA := .Values.agentServiceAccount }} +{{ $namespace := .Release.Namespace }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: appdynamics-cluster-agent-instrumentation-{{.Release.Name}} +subjects: + {{- printf "- kind: ServiceAccount" | nindent 2 }} + {{- printf "name: %s" $agentSA | nindent 4 }} + {{- printf "namespace: %s" $namespace | nindent 4}} +roleRef: + kind: ClusterRole + name: appdynamics-cluster-agent-instrumentation-{{.Release.Name}} + apiGroup: rbac.authorization.k8s.io +{{- end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/infraviz-security-context-constraint-openshift.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/infraviz-security-context-constraint-openshift.yaml new file mode 100644 index 00000000..93a65bd3 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/infraviz-security-context-constraint-openshift.yaml @@ -0,0 +1,35 @@ +{{ if .Values.installInfraViz -}} +{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1/SecurityContextConstraints" -}} +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + name: appdynamics-infraviz +allowHostDirVolumePlugin: true +allowHostIPC: true +allowHostNetwork: true +allowHostPID: true +allowHostPorts: true +allowPrivilegedContainer: true +allowedCapabilities: +- '*' +allowedFlexVolumes: null +defaultAddCapabilities: null +fsGroup: + type: RunAsAny +priority: null +readOnlyRootFilesystem: false +requiredDropCapabilities: null +runAsUser: + type: RunAsAny +seLinuxContext: + type: RunAsAny +seccompProfiles: +- '*' +supplementalGroups: + type: RunAsAny +users: +- system:serviceaccount:appdynamics:appdynamics-infraviz +volumes: +- '*' +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/sa-agent.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/sa-agent.yaml new file mode 100644 index 00000000..3eb71ddc --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/sa-agent.yaml @@ -0,0 +1,9 @@ +{{ if .Values.installClusterAgent -}} +{{ if .Values.createServiceAccount -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.agentServiceAccount }} + namespace: {{ .Release.Namespace }} +{{ end -}} +{{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/sa-infraviz.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/sa-infraviz.yaml new file mode 100644 index 00000000..410c3bd8 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/sa-infraviz.yaml @@ -0,0 +1,7 @@ +{{ if .Values.installInfraViz -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.infravizServiceAccount }} + namespace: {{ .Release.Namespace }} +{{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-cluster-agent.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-cluster-agent.yaml new file mode 100644 index 00000000..a4483080 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-cluster-agent.yaml @@ -0,0 +1,27 @@ +{{ $secret := (lookup "v1" "Secret" .Release.Namespace "cluster-agent-secret") }} +{{ $annotations := dict "temp" "temp" }} +{{ if $secret }} + {{ $annotations = $secret.metadata.annotations }} +{{ end }} +{{ if or (not ($secret)) (get $annotations "appdynamics.helm.charts/created-by") }} +{{ $namespace := .Release.Namespace }} +{{ if .Values.installClusterAgent -}} +apiVersion: v1 +kind: Secret +metadata: + name: cluster-agent-secret + namespace: {{ $namespace }} + annotations: + appdynamics.helm.charts/created-by: cluster-agent-helm-chart +type: Opaque +data: + {{ with .Values.controllerInfo -}} + controller-key: {{ include "appdynamics-csaas-k8s-cluster-agent.sensitiveData" (dict "data" .accessKey "message" "AppDynamics controller access key is required!") }} + {{- end -}} + {{ if .Values.instrumentationConfig.enabled -}} + {{ with .Values.controllerInfo }} + api-user: {{ cat (.username | trim | required "AppDynamics controller username is required!") "@" (.account | trim | required "AppDynamics controller account is required!") ":" (.password | trim | required "Appdynamics controller password is required!") | nospace | b64enc -}} + {{- end -}} + {{- end -}} +{{ end -}} +{{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-custom-ssl.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-custom-ssl.yaml new file mode 100644 index 00000000..ce4d9999 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-custom-ssl.yaml @@ -0,0 +1,22 @@ +{{ $secret := (lookup "v1" "Secret" .Release.Namespace "cluster-agent-ssl-cert") }} +{{ $annotations := dict "temp" "temp" }} +{{ if $secret }} + {{ $annotations = $secret.metadata.annotations }} +{{ end }} +{{ if or (not ($secret)) (get $annotations "appdynamics.helm.charts/created-by") }} +{{ $namespace := .Release.Namespace }} +{{ with .Values -}} +{{ if .controllerInfo.customSSLCert -}} +apiVersion: v1 +kind: Secret +metadata: + name: cluster-agent-ssl-cert + namespace: {{ $namespace }} + annotations: + appdynamics.helm.charts/created-by: cluster-agent-helm-chart +type: Opaque +data: + "custom-ssl.pem": {{ .controllerInfo.customSSLCert }} +{{ end -}} +{{ end -}} +{{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-proxy-secret.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-proxy-secret.yaml new file mode 100644 index 00000000..18a61ded --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-proxy-secret.yaml @@ -0,0 +1,25 @@ +{{ $secret := (lookup "v1" "Secret" .Release.Namespace "cluster-agent-proxy-secret") }} +{{ $annotations := dict "temp" "temp" }} +{{ if $secret }} + {{ $annotations = $secret.metadata.annotations }} +{{ end }} +{{ if or (not ($secret)) (get $annotations "appdynamics.helm.charts/created-by") }} +{{ $namespace := .Release.Namespace }} +{{ with .Values -}} +{{ if .controllerInfo.authenticateProxy -}} +{{ if not .controllerInfo.proxyUrl -}} +{{ fail "Proxy url is requried to authenticate proxy!" -}} +{{ end -}} +apiVersion: v1 +kind: Secret +metadata: + name: cluster-agent-proxy-secret + namespace: {{ $namespace }} + annotations: + appdynamics.helm.charts/created-by: cluster-agent-helm-chart +type: Opaque +data: + proxy-password: {{ include "appdynamics-csaas-k8s-cluster-agent.sensitiveData" (dict "data" .controllerInfo.proxyPassword "message" "Proxy password is required!") }} +{{ end -}} +{{ end -}} +{{ end -}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/values.yaml new file mode 100644 index 00000000..06a84977 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/values.yaml @@ -0,0 +1,136 @@ +installClusterAgent: false +installInfraViz: false + +# Docker images +imageInfo: + agentImage: docker.io/appdynamics/cluster-agent + agentTag: 24.1.0 + imagePullPolicy: Always # Will be used for operator pod + machineAgentImage: docker.io/appdynamics/machine-agent + machineAgentTag: latest + machineAgentWinImage: docker.io/appdynamics/machine-agent-analytics + machineAgentWinTag: win-latest + netVizImage: docker.io/appdynamics/machine-agent-netviz + netvizTag: latest + +# AppDynamics controller info (VALUES TO BE PROVIDED BY THE USER) +controllerInfo: + url: null + account: null + username: null + password: null + accessKey: null + globalAccount: null # To be provided when using machineAgent Window Image + + # Cluster Agent SSL properties + customSSLCert: null + # InfraViz SSL properties + keystorePasswordSecret: "" + keyStoreFileSecret: "" + + # Proxy config + authenticateProxy: false + proxyUrl: null + proxyUser: null + proxyPassword: null + +# RBAC config +createServiceAccount: true +agentServiceAccount: appdynamics-cluster-agent +infravizServiceAccount: appdynamics-infraviz + +# Cluster agent config +clusterAgent: + nsToMonitor: + - default + clusterMetricsSyncInterval: 60 + metadataSyncInterval: 60 + eventUploadInterval: 10 + httpClientTimeout: 30 + podBatchSize: 6 + instrumentationMaxPollingAttempts: 10 + instrumentationNsStatusPollingIntervalMinutes: 5 + imagePullPolicy: "" + imagePullSecret: "" + memoryThresholdForRestart: 90 + containerProperties: + containerBatchSize: 5 + containerParallelRequestLimit: 1 + containerRegistrationInterval: 120 + logProperties: + logFileSizeMb: 5 + logFileBackups: 3 + logLevel: INFO + metricProperties: + metricsSyncInterval: 30 + metricUploadRetryCount: 2 + metricUploadRetryIntervalMilliSeconds: 5 + +# Profiling specific config - set pprofEnabled true if profiling need to be enabled, +# provide pprofPort if you need different port else default port 9991 will be assigned +agentProfiler: + pprofEnabled: false + pprofPort: 9991 + +# Pod filter config +podFilter: {} + +# Instrumentation config +instrumentationConfig: + enabled: false + containerAppCorrelationMethod: proxy + +# InfraViz config +infraViz: + nodeOS: "linux" + enableMasters: false + stdoutLogging: false + enableContainerHostId: true + enableServerViz: false + enableDockerViz: false + +# Netviz config +netViz: + enabled: false + netVizPort: 3892 + resourcesNetViz: + limits: + cpu: 200m + memory: "300Mi" + requests: + cpu: 100m + memory: "150Mi" + +# Agent pod specific properties +agentPod: + nodeSelector: {} + tolerations: [] + resources: + limits: + cpu: "1250m" + memory: "300Mi" + requests: + cpu: "750m" + memory: "150Mi" + labels: {} + +# Infraviz pod specific properties +infravizPod: + imagePullSecret: "" + nodeSelector: + kubernetes.io/os: linux + tolerations: [] + priorityClassName: "" + resources: + limits: + cpu: 500m + memory: "1G" + requests: + cpu: 200m + memory: "800M" + overrideVolumeMounts: + env: + +# Subcharts boolean install switches +install: + metrics-server: false diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/Chart.yaml new file mode 100644 index 00000000..bcdd771b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/Chart.yaml @@ -0,0 +1,8 @@ +apiVersion: v2 +appVersion: 24.2.0 +description: AppDynamics Network Monitoring Helm chart for Kubernetes +maintainers: +- email: support@appdynamics.com + name: AppDynamics +name: appdynamics-network-monitoring +version: 0.2.0 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/_helpers.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/_helpers.tpl new file mode 100644 index 00000000..673b7445 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/_helpers.tpl @@ -0,0 +1,66 @@ +{{/* +Fully qualified app name for the kernel-collector daemonset. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "appdynamics-network-monitoring-kernel-collector.fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-kernel-collector" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-kernel-collector" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the kernel-collector +*/}} +{{- define "appdynamics-network-monitoring-kernel-collector.serviceAccountName" -}} +{{- if .Values.kernelCollector.serviceAccount.create }} +{{- default (include "appdynamics-network-monitoring-kernel-collector.fullname" .) .Values.kernelCollector.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.kernelCollector.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Fully qualified app name for the k8s-collector deployment. +*/}} +{{- define "appdynamics-network-monitoring-k8s-collector.fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-k8s-collector" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-k8s-collector" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the k8s-collector +*/}} +{{- define "appdynamics-network-monitoring-k8s-collector.serviceAccountName" -}} +{{- if .Values.k8sCollector.serviceAccount.create }} +{{- default (include "appdynamics-network-monitoring-k8s-collector.fullname" .) .Values.k8sCollector.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.k8sCollector.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Fully qualified app name for the reducer deployment. +*/}} +{{- define "appdynamics-network-monitoring-reducer.fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-reducer" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-reducer" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "appdynamics-network-monitoring.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-clusterrole.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-clusterrole.yaml new file mode 100644 index 00000000..7831cf12 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-clusterrole.yaml @@ -0,0 +1,34 @@ +{{- if and .Values.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app: {{ include "appdynamics-network-monitoring-k8s-collector.fullname" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + name: {{ include "appdynamics-network-monitoring-k8s-collector.fullname" . }} +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch +- apiGroups: + - apps + resources: + - replicasets + verbs: + - get + - list + - watch +- apiGroups: + - batch + resources: + - jobs + verbs: + - get + - list + - watch +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-clusterrolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-clusterrolebinding.yaml new file mode 100644 index 00000000..5cf0bda8 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-clusterrolebinding.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app: {{ include "appdynamics-network-monitoring-k8s-collector.fullname" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + name: {{ include "appdynamics-network-monitoring-k8s-collector.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "appdynamics-network-monitoring-k8s-collector.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ include "appdynamics-network-monitoring-k8s-collector.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-deployment.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-deployment.yaml new file mode 100644 index 00000000..0fe529ea --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-deployment.yaml @@ -0,0 +1,81 @@ +{{- if and .Values.enabled .Values.k8sCollector.enabled }} +# The k8s-collector consists of two services: +# 1) k8s-watcher: talks to the Kubernetes API server to determine the current state of +# the cluster; sets up watches to be notified of subsequent changes to pods, services +# and other resources. +# 2) k8s-relay: relays the information collected by k8s-watcher to the reducer. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "appdynamics-network-monitoring-k8s-collector.fullname" . }} + labels: + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-k8s-collector.fullname" . }} + helm.sh/chart: {{ include "appdynamics-network-monitoring.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + progressDeadlineSeconds: 600 + replicas: 1 + revisionHistoryLimit: 3 + selector: + matchLabels: + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-k8s-collector.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-k8s-collector.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + {{- with .Values.k8sCollector.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8}} + {{- end }} + containers: + - image: "{{ .Values.k8sCollector.watcher.image }}" + imagePullPolicy: {{ .Values.k8sCollector.watcher.imagePullPolicy }} + name: k8s-watcher + {{- if hasKey .Values.k8sCollector.watcher "resources" }} + resources: + {{- toYaml .Values.k8sCollector.watcher.resources | nindent 10 }} + {{- end }} + args: + - --log-console + {{- if hasKey .Values.log "level" }} + - --log-level={{ .Values.log.level }} + {{- end }} + - image: "{{ .Values.k8sCollector.relay.image }}" + imagePullPolicy: {{ .Values.k8sCollector.relay.imagePullPolicy }} + name: k8s-relay + {{- if hasKey .Values.k8sCollector.relay "resources" }} + resources: + {{- toYaml .Values.k8sCollector.relay.resources | nindent 10 }} + {{- end }} + args: + {{- if .Values.log.console }} + - --log-console + {{- end }} + {{- if hasKey .Values.log "level" }} + - --{{ .Values.log.level }} + {{- end }} + env: + - name: "EBPF_NET_INTAKE_HOST" + value: {{ include "appdynamics-network-monitoring-reducer.fullname" . }} + - name: "EBPF_NET_INTAKE_PORT" + value: "{{ default 7000 .Values.reducer.telemetryPort }}" + terminationGracePeriodSeconds: 30 + securityContext: {} + serviceAccountName: {{ include "appdynamics-network-monitoring-k8s-collector.serviceAccountName" . }} + {{- with .Values.k8sCollector.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.k8sCollector.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.k8sCollector.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-serviceaccount.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-serviceaccount.yaml new file mode 100644 index 00000000..d09a4e16 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-serviceaccount.yaml @@ -0,0 +1,9 @@ +{{- if and .Values.enabled .Values.k8sCollector.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: {{ include "appdynamics-network-monitoring-k8s-collector.fullname" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + name: {{ include "appdynamics-network-monitoring-k8s-collector.serviceAccountName" . }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/kernel-collector-daemonset.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/kernel-collector-daemonset.yaml new file mode 100644 index 00000000..fc0b5392 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/kernel-collector-daemonset.yaml @@ -0,0 +1,92 @@ +{{- if and .Values.enabled .Values.kernelCollector.enabled }} +# kernel collector daemonset: deploys the kernel collector to each node in the cluster. +# The kernel collector needs to be able to compile and install +# eBPF programs in the node's kernel, so needs to run as root and +# needs to mount /lib/modules and /usr/src from the node itself. +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "appdynamics-network-monitoring-kernel-collector.fullname" . }} + labels: + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-kernel-collector.fullname" . }} + helm.sh/chart: {{ include "appdynamics-network-monitoring.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-kernel-collector.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-kernel-collector.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + {{- with .Values.kernelCollector.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8}} + {{- end }} + containers: + - name: kernel-collector + image: "{{ .Values.kernelCollector.image }}" + imagePullPolicy: {{ .Values.kernelCollector.imagePullPolicy }} + args: + - --disable-nomad-metadata + {{- if .Values.log.console }} + - --log-console + {{- end }} + {{- if hasKey .Values.log "level" }} + - --{{ .Values.log.level }} + {{- end }} + env: + - name: "EBPF_NET_KERNEL_HEADERS_AUTO_FETCH" + value: "true" + - name: "EBPF_NET_INTAKE_HOST" + value: {{ include "appdynamics-network-monitoring-reducer.fullname" . }} + - name: "EBPF_NET_INTAKE_PORT" + value: "{{ default 7000 .Values.reducer.telemetryPort }}" + - name: "EBPF_NET_HOST_DIR" + value: "/hostfs" + {{- if .Values.kernelCollector.env }} + {{- toYaml .Values.kernelCollector.env | nindent 12 }} + {{- end }} + {{- if hasKey .Values.kernelCollector "resources" }} + resources: + {{- toYaml .Values.kernelCollector.resources | nindent 12 }} + {{- end }} + securityContext: + privileged: true + volumeMounts: + - mountPath: /hostfs/ + name: host-root + readOnly: true + - mountPath: /hostfs/var/cache + name: host-var-cache + readOnly: false + dnsPolicy: ClusterFirstWithHostNet + hostNetwork: true + hostPID: true + serviceAccountName: {{ include "appdynamics-network-monitoring-kernel-collector.serviceAccountName" . }} + volumes: + - name: host-root + hostPath: + path: / + type: Directory + - name: host-var-cache + hostPath: + path: /var/cache + type: DirectoryOrCreate + {{- with .Values.kernelCollector.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.kernelCollector.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.kernelCollector.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/kernel-collector-serviceaccount.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/kernel-collector-serviceaccount.yaml new file mode 100644 index 00000000..1fc03c4e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/kernel-collector-serviceaccount.yaml @@ -0,0 +1,9 @@ +{{- if and .Values.enabled .Values.kernelCollector.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: {{ include "appdynamics-network-monitoring-kernel-collector.fullname" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + name: {{ include "appdynamics-network-monitoring-kernel-collector.serviceAccountName" . }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/reducer-deployment.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/reducer-deployment.yaml new file mode 100644 index 00000000..6717f52d --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/reducer-deployment.yaml @@ -0,0 +1,82 @@ +{{- if .Values.enabled}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "appdynamics-network-monitoring-reducer.fullname" . }} + labels: + helm.sh/chart: {{ include "appdynamics-network-monitoring.chart" . }} + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-reducer.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-reducer.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-reducer.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + {{- with .Values.reducer.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8}} + {{- end }} + containers: + - name: reducer + image: "{{ .Values.reducer.image }}" + imagePullPolicy: {{ .Values.reducer.imagePullPolicy }} + args: + - --port={{- .Values.reducer.telemetryPort }} + - --log-console + - --no-log-file + {{- if hasKey .Values.log "level" }} + - --{{ .Values.log.level }} + {{- end }} + - --disable-prometheus-metrics + - --enable-otlp-grpc-metrics + - --otlp-grpc-metrics-host=appdynamics-otel-collector-service + - --otlp-grpc-metrics-port=24317 + {{- if .Values.reducer.disableMetrics }} + - --disable-metrics={{join "," .Values.reducer.disableMetrics}} + {{- end }} + {{- if .Values.reducer.enableMetrics }} + - --enable-metrics={{join "," .Values.reducer.enableMetrics}} + {{- end }} + {{- if .Values.reducer.ingestShards }} + - --num-ingest-shards={{- .Values.reducer.ingestShards }} + {{- end }} + {{- if .Values.reducer.matchingShards }} + - --num-matching-shards={{- .Values.reducer.matchingShards }} + {{- end }} + {{- if .Values.reducer.aggregationShards }} + - --num-aggregation-shards={{- .Values.reducer.aggregationShards }} + {{- end }} + ports: + - name: telemetry + containerPort: {{ .Values.reducer.telemetryPort }} + protocol: TCP + readinessProbe: + initialDelaySeconds: 5 + periodSeconds: 20 + timeoutSeconds: 5 + exec: + command: ['/srv/health_check.sh', 'readiness_probe', 'localhost', {{ quote .Values.reducer.telemetryPort }}] + resources: + {{- toYaml .Values.reducer.resources | nindent 12 }} + {{- with .Values.reducer.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.reducer.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.reducer.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/reducer-service.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/reducer-service.yaml new file mode 100644 index 00000000..681dcbb5 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/reducer-service.yaml @@ -0,0 +1,22 @@ +{{- if .Values.enabled}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "appdynamics-network-monitoring-reducer.fullname" . }} + labels: + helm.sh/chart: {{ include "appdynamics-network-monitoring.chart" . }} + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-reducer.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: {{ include "appdynamics-network-monitoring-reducer.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + ports: + - name: telemetry + port: {{ .Values.reducer.telemetryPort }} + targetPort: telemetry + protocol: TCP +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/values.schema.json b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/values.schema.json new file mode 100644 index 00000000..29806acf --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/values.schema.json @@ -0,0 +1,155 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "title": "Values", + "description": "AppDynamics Network Monitoring Configuration", + "additionalProperties": false, + "properties": { + "global": { + "type": "object", + "properties": { + "clusterName": { + "description": "The name for cluster where the collectors and target allocator are deployed", + "type": "string" + }, + "clusterId": { + "description": "The uid of kube-system namespace, required when helm lookup is not supported", + "type": "string" + } + }, + "required": [ + "clusterName" + ] + }, + "enabled": { + "description": "Enable network monitoring", + "type": "boolean" + }, + "nameOverride": { + "description": "Override name of the chart used in Kubernetes object names.", + "type": "string" + }, + "log": { + "type": "object", + "additionalProperties": false, + "properties": { + "console": { + "type": "boolean" + }, + "level": { + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug", + "trace" + ] + } + } + }, + "kernelCollector": { + "type": "object", + "properties": { + "image": { + "type": "string" + }, + "imagePullPolicy": { + "type": "string", + "enum": [ + "IfNotPresent", + "Always", + "Never" + ] + }, + "imagePullSecrets": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": true + }, + "k8sCollector": { + "type": "object", + "properties": { + "relay": { + "type": "object", + "properties": { + "image": { + "type": "string" + }, + "imagePullPolicy": { + "type": "string", + "enum": [ + "IfNotPresent", + "Always", + "Never" + ] + } + }, + "additionalProperties": true + }, + "watcher": { + "type": "object", + "properties": { + "image": { + "type": "string" + }, + "imagePullPolicy": { + "type": "string", + "enum": [ + "IfNotPresent", + "Always", + "Never" + ] + } + }, + "additionalProperties": true + }, + "imagePullSecrets": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": true + }, + "reducer": { + "type": "object", + "properties": { + "image": { + "type": "string" + }, + "imagePullPolicy": { + "type": "string", + "enum": [ + "IfNotPresent", + "Always", + "Never" + ] + }, + "imagePullSecrets": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": true + }, + "rbac": { + "type": "object", + "additionalProperties": false, + "properties": { + "create": { + "type": "boolean" + } + } + } + }, + "required": [], + "anyOf": [] +} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/values.yaml new file mode 100644 index 00000000..92e150ed --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/values.yaml @@ -0,0 +1,80 @@ +global: + clusterName: "" + tls: + otelReceiver: + secret: {} + settings: {} + otelExporter: + secret: {} + settings: {} + +enabled: false +nameOverride: "" + +log: + console: false + # possible values: { error | warning | info | debug | trace } + level: warning + +kernelCollector: + enabled: true + image: otel/opentelemetry-ebpf-kernel-collector:v0.10.2 + imagePullPolicy: Always + imagePullSecrets: [] + nodeSelector: + kubernetes.io/arch: amd64 + kubernetes.io/os: linux + + serviceAccount: + create: false + name: "" + + tolerations: + - operator: "Exists" + effect: "NoExecute" + - operator: "Exists" + effect: "NoSchedule" + + affinity: {} + resources: {} + +k8sCollector: + enabled: true + relay: + image: otel/opentelemetry-ebpf-k8s-relay:v0.10.2 + imagePullPolicy: Always + resources: {} + watcher: + image: otel/opentelemetry-ebpf-k8s-watcher:v0.10.2 + imagePullPolicy: Always + resources: {} + imagePullSecrets: [] + nodeSelector: + kubernetes.io/arch: amd64 + kubernetes.io/os: linux + affinity: {} + tolerations: [] + serviceAccount: + create: false + name: "" + +reducer: + ingestShards: 1 + matchingShards: 1 + aggregationShards: 1 + disableMetrics: + - ebpf_net.all + enableMetrics: [] + telemetryPort: 7000 + image: otel/opentelemetry-ebpf-reducer:v0.10.2 + imagePullPolicy: Always + imagePullSecrets: [] + resources: {} + nodeSelector: + kubernetes.io/arch: amd64 + kubernetes.io/os: linux + affinity: {} + tolerations: [] + +rbac: + create: true diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/Chart.yaml new file mode 100644 index 00000000..0438e802 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/Chart.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +appVersion: 24.4.1-1600 +description: AppDynamics distributed Opentelemetry Collector Helm chart for Kubernetes +maintainers: +- email: support@appdynamics.com + name: AppDynamics +name: appdynamics-otel-collector +version: 24.4.1-1600 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/README.md b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/README.md new file mode 100644 index 00000000..5e30eeaa --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/README.md @@ -0,0 +1,71 @@ +# Helm chart for Appd collector with Opentelemetry Operator + +## Required Values +Some components, if used, required user input value. + +### OtlpHttp Exporter +OtlpHttp exporter need to specify backend endpoint and Ouath2 related properties: +These are required values: +```yaml +clientId: "id" # clientId for oauth2 extension +tokenUrl: "https://token_ur.com/oauth2l" # tokenUrl for oauth2 extension +endpoint: "https://data.appdynamics.com" # endpoint for otlphttp exporeter +``` +Client secret can be presented in plain text(clientSecret) or environment variable(clientSecretEnvVar) and at least one of them must be provided. +when clientSecret and clientSecretEnvVar are both provided, clientSecret will be used. +```yaml +# clientSecret plain text for oauth2 extension +clientSecret: "secret" + +# clientSecret set by environment variable for oauth2 extension +# When using this format, the value will be set to environment variable APPD_OTELCOL_CLIENT_SECRET, and +# collector config will read the secret from ${APPD_OTELCOL_CLIENT_SECRET}. +clientSecretEnvVar: + value: "secret" +``` +clientSecretEnvVar can be used for kubernetes secret. +```yaml +# clientSecret set by environment variable which value is read from kubernetes secret. +clientSecret: + valueFrom: + secretKeyRef: + name: "oauth-client-secret" + key: "secret" +``` +example for configuring values by helm command line: +```shell +helm install release-name appdynamics-otel-collector \ + --set clientId="clientId" \ + --set clientSecretEnvVar.secretKeyRef.name="oauth-client-secret" \ + --set clientSecretEnvVar.secretKeyRef.key="secret" \ + --set tokenUrl="https://example-token-url" \ + --set endpoint="https://example:443/v1beta/metrics" +``` +You can also disable Oauth2 for testing, please be aware you will also need to remove all related configs manually include exporter config and pipeline. +see examples/remove_oauth.yaml. + +### Prometheus Receiver +Prometheus receiver if used, must have at least one scrape config, following showed an example k8s pod discovery config. +```yaml +prometheus: + config: + scrape_configs: + - job_name: k8s + kubernetes_sd_configs: + - role: pod + # namespace must be manually specified, otherwise prometheus will explore all namespaces. + namespaces: + names: [ "default" ] + relabel_configs: + - source_labels: [ __meta_kubernetes_pod_annotation_prometheus_io_scrape ] + regex: "true" + action: keep +``` +If using k8s discovery scape, don't forget to give necessary rbac rules. +```yaml +rbac: + rules: + - apiGroups: [ "" ] + resources: [ "pods" ] + verbs: [ "get", "list", "watch" ] +``` \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/client_secret_env.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/client_secret_env.yaml new file mode 100644 index 00000000..35e42b30 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/client_secret_env.yaml @@ -0,0 +1,8 @@ +clientId: "id" +clientSecretEnvVar: + valueFrom: + secretKeyRef: + name: "oauth-client-secret" + key: "secret" +tokenUrl: "https://token_ur.com/oauth2l" +endpoint: "https://data.appdynamics.com" \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/headless_service.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/headless_service.yaml new file mode 100644 index 00000000..d56d949f --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/headless_service.yaml @@ -0,0 +1,10 @@ +# required +endpoint: "https://data.appdynamics.com" +clientId: "id" +clientSecret: "secret" +tokenUrl: "https://token_ur.com/oauth2l" + +# If your cluster does not deploy the service mesh that can do http/2 load balancing for grpc, +# we recommended to deploy the otel collector with a headless service to enable the grpc client load balance. +service: + clusterIP: None \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/instrumentation.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/instrumentation.yaml new file mode 100644 index 00000000..0b676525 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/instrumentation.yaml @@ -0,0 +1,12 @@ +# required +endpoint: "https://data.appdynamics.com" +clientId: "id" +clientSecret: "secret" +tokenUrl: "https://token_ur.com/oauth2l" + +# add namespace you want to instrument +# The resources you want to instrument should have annotation: +# instrumentation.opentelemetry.io/inject-: "true" +instrumentation: + namespaces: + default: diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/instrumentation_tls.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/instrumentation_tls.yaml new file mode 100644 index 00000000..a730cc25 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/instrumentation_tls.yaml @@ -0,0 +1,33 @@ +global: + tls: + otelReceiver: + secret: + secretName: root-secret + secretKeys: + tlsCert: tls.crt + tlsKey: tls.key + settings: + min_version: 1.2 + max_version: 1.3 +# required +endpoint: "https://data.appdynamics.com" +clientId: "id" +clientSecret: "secret" +tokenUrl: "https://token_ur.com/oauth2l" + +# add namespace you want to instrument +# The resources you want to instrument should have annotation: +# instrumentation.opentelemetry.io/inject-: "true" +instrumentation: +# by default insecure is true, when insecure is false, tls will be used to protect the communication with AppDynamics Distribution of OpenTelemetry Collector. + insecure: false + namespaces: + default: + metadata: + labels: + my-label: tls + spec: + java: + env: + - name: OTEL_EXPORTER_OTLP_CERTIFICATE # The tls.crt should contain dns name appdynamics-otel-collector-service.appdynamics.svc.cluster.local + value: /etc/agent/cert/tls.crt # path to the crt should exist in the instrumented pod. \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/not_installed.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/not_installed.yaml new file mode 100644 index 00000000..767c5b28 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/not_installed.yaml @@ -0,0 +1,2 @@ +# Sample values.yaml received by this sub-chart when flag is set to false +install: false \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/prometheus.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/prometheus.yaml new file mode 100644 index 00000000..ad2bd1d6 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/prometheus.yaml @@ -0,0 +1,11 @@ +# required +global: + clusterName: "my-cluster" +endpoint: "https://data.appdynamics.com" +clientId: "dummy" +clientSecret: "dummy" +tokenUrl: "dummy" +enablePrometheus: true +# Replicas must set to enable the collector deployment, you can also set minReplicas and maxReplicas to enable autoscaling +spec: + replicas: 2 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/prometheus_and_filelog.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/prometheus_and_filelog.yaml new file mode 100644 index 00000000..0d3bd528 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/prometheus_and_filelog.yaml @@ -0,0 +1,19 @@ +# required +global: + clusterName: "my-cluster" +endpoint: "https://data.appdynamics.com" +clientId: "dummy" +clientSecret: "dummy" +tokenUrl: "dummy" +enablePrometheus: true +enableFileLog: true +# set replicas for statefulset which gathers prometheus metrics, you can also set minReplicas and maxReplicas to enable autoscaling +mode: + statefulset: + spec: + replicas: 2 + daemonset: + configOverride: + receivers: + filelog: + include: ["/var/log/*/*/*/*.log", "/var/lib/docker/containers/*"] diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/remove_oauth.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/remove_oauth.yaml new file mode 100644 index 00000000..3e000cb5 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/remove_oauth.yaml @@ -0,0 +1,17 @@ +# required +endpoint: "https://data.appdynamics.com" +# Dummy values for oauth2 is required. This is a test example to disable oauth2, do NOT use it in production. +clientId: "dummy" +clientSecret: "dummy" +tokenUrl: "dummy" + +configOverride: + # remove auth field from otlp exporter + exporters: + otlphttp: + auth: null + # to disbale oauth2 remove from service section. The below is the default. + # service: + # extensions: [health_check, oauth2client] + service: + extensions: [health_check] diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/self_telemetry.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/self_telemetry.yaml new file mode 100644 index 00000000..c4a37f49 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/self_telemetry.yaml @@ -0,0 +1,11 @@ +# required +endpoint: "https://data.appdynamics.com" +clientId: "dummy" +clientSecret: "dummy" +tokenUrl: "dummy" + +# self telemetry +selfTelemetry: true +setPodUID: true +# selfTelemetryServiceName: "appd-otel-collector1" +# selfTelemetryServiceNamespace: "otelcol1" \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/simple.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/simple.yaml new file mode 100644 index 00000000..dc64aba2 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/simple.yaml @@ -0,0 +1,11 @@ +# required +endpoint: "https://data.appdynamics.com" +clientId: "id" +clientSecret: "secret" +tokenUrl: "https://token_ur.com/oauth2l" +configOverride: + service: + pipelines: + traces: + exporters: [ otlphttp, logging ] + diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tailsampling.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tailsampling.yaml new file mode 100644 index 00000000..92154992 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tailsampling.yaml @@ -0,0 +1,62 @@ +global: + clusterName: clusterName + clusterId: testid + +# required +endpoint: "https://data.appdynamics.com" +clientId: "id" +clientSecret: "secret" +tokenUrl: "https://token_ur.com/oauth2l" + +spec: + image: "829771730735.dkr.ecr.us-west-2.amazonaws.com/otel/appdynamics-cloud-otel-collector:23.7.0-1075" + +presets: + samplerDebug: + enable: false + presampler: + enable: false + #pipeline: [memory_limiter, k8sattributes, consistent_proportional_sampler/presampler, batch/traces] + pipeline: [memory_limiter, k8sattributes, tracerecord/received, consistent_sampler/presampler, tracerecord/sampled, batch/traces] #replace with this pipeline when testing adding configured p value directly. + consistent_proportional_sampler: + export_period: 1s # the export period for specifying the expected output rate, it is for rate calculation only, NOT for batch interval. The batch interval can be configured at trace_classification_and_sampling.samplers.export_period, or you can add a batch processor before this. + spans_per_period: 100 # number of spans per request, the expected rate limit is calculated by dividing this number by export_period. The spans per packet is limited by the max packet size, assuming 1MB limit, and each span with size of 1KB + exponential_smooth: 0.1 # start with small number + initial_estimate_rate: 100 # number of incomming span rate, just give a reasonable guess. + rate_estimator: batch_rate_estimator + sample_mode: presampling + consistent_sampler: + p_value: 1 # user can configure a p value to add to the trace state directly, it is mainly for testing purpose + tailsampler: + enable: true + trace_classification_and_sampling: + decision_wait: 10s + # classification, example considers error, high latency and all other traces, each category will be rate limit separately. + policies: + - name: errors-policy + type: status_code + sampler_name: "consistent_reservoir_sampler/error" + status_code: + status_codes: [ERROR] + - name: high-latency + type: latency + sampler_name: "consistent_reservoir_sampler/latency" + latency: + threshold_ms: 10000 + - name: always-on + type: always_sample + sampler_name: "consistent_reservoir_sampler/anyother" + samplers: + export_period: 1s # export interval. The overall request rate need to be multiplied the number of collector, tier one is 1000 req/sec, https://docs.appdynamics.com/fso/cloud-native-app-obs/en/licensing-for-cloud-native-application-observability/license-tokens-tiers-and-rate-limits + consistent_reservoir_sampler: + error: + reservoir_size: 10 + latency: + reservoir_size: 10 + anyother: + reservoir_size: 100 + consistent_proportional_sampler: + export_period: 1s # the export period for specifying the expected output rate, it is for rate calculation only, NOT for batch interval. The batch interval can be configured at trace_classification_and_sampling.samplers.export_period, or you can add a batch processor before this. + spans_per_period: 100 # number of spans per request, the expected rate limit is calculated by dividing this number by export_period. The spans per packet is limited by the max packet size, assuming 1MB limit, and each span with size of 1KB + exponential_smooth: 0.1 # start with small number + initial_estimate_rate: 100 # number of incomming span rate, just give a reasonable guess. diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_from_secret_exporter.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_from_secret_exporter.yaml new file mode 100644 index 00000000..35bee740 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_from_secret_exporter.yaml @@ -0,0 +1,20 @@ +# required +clientId: "id" +clientSecret: "secret" +tokenUrl: "https://token_ur.com/oauth2l" +endpoint: "https://data.appdynamics.com" + +global: + tls: + otelExporter: + secret: + path: /opt/appd + secretName: my_secret + secretKeys: + caCert: ca.crt + tlsCert: tls.crt + tlsKey: tls.key + settings: + insecure: false + min_version: 1.2 + max_version: 1.3 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_from_secret_receiver.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_from_secret_receiver.yaml new file mode 100644 index 00000000..1f53aae8 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_from_secret_receiver.yaml @@ -0,0 +1,19 @@ +# required +clientId: "id" +clientSecret: "secret" +tokenUrl: "https://token_ur.com/oauth2l" +endpoint: "https://data.appdynamics.com" + +global: + tls: + otelReceiver: + secret: + secretName: otel-cert + secretKeys: + caCert: ca.crt + tlsCert: tls.crt + tlsKey: tls.key + settings: + min_version: 1.2 + max_version: 1.3 + diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_values.yaml new file mode 100644 index 00000000..29abfd04 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_values.yaml @@ -0,0 +1,23 @@ +# required +clientId: "id" +clientSecret: "secret" +tokenUrl: "https://token_ur.com/oauth2l" +endpoint: "https://data.appdynamics.com" + +global: + tls: + otelReceiver: + settings: + min_version: 1.2 + max_version: 1.3 + ca_file: /etc/ssl/client.pem + cert_file: /etc/ssl/server.crt + key_file: /etc/ssl/server.key + #reload_interval: 5s + otelExporter: + settings: + insecure: false + cert_file: /etc/ssl/client.crt + key_file: /etc/ssl/client.key + min_version: "1.1" + max_version: "1.2" diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/NOTES.txt b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/NOTES.txt new file mode 100644 index 00000000..69ba716e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/NOTES.txt @@ -0,0 +1,28 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +AppDynamics OpenTelemetry Collectors are listening for OTLP traffic at service "{{ .Values.service.name }}". + +The following components are enabled for logs, metrics and traces. + +{{.Values.config.service | toYaml }} + + +Check the release status by running: + kubectl --namespace {{ .Release.Namespace }} get pods | grep -i {{ .Release.Name }} + +For details about OpenTelemetry Collector configuration, please go to +https://docs.appdynamics.com/latest/en/application-monitoring/appdynamics-for-opentelemetry/configure-the-opentelemetry-collector + + +THIRD PARTY LICENSE DISCLOSURE +=============================== +AppDynamics OpenTelemetry Collector +-------------------------------------------------- +https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/AppDynamics_Distribution_for_OpenTelemetry_Collector-2441-1714020313.pdf + + + diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_agent_management_and_global_input.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_agent_management_and_global_input.tpl new file mode 100644 index 00000000..9acab4a2 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_agent_management_and_global_input.tpl @@ -0,0 +1,107 @@ +{{- define "appdynamics-otel-collector.namespace" -}} +{{- if .Values.global.smartAgentInstall -}} +{{- default .Release.Namespace .Values.global.namespace }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.cluster.name" -}} +{{- if .Values.global.smartAgentInstall -}} +{{ "AGENT_PLATFORM_NAME_VALUE" }} +{{- else -}} +{{ required "clusterName needs to be specified" .Values.global.clusterName }} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.clusterId" -}} +{{- if .Values.global.smartAgentInstall -}} +{{ "AGENT_PLATFORM_ID_VALUE" }} +{{- else -}} +{{ (include "appdynamics-otel-collector.readClusterId" .) }} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.derivedOAuth" -}} +{{- if .Values.global.smartAgentInstall -}} +client_id: {{ "OAUTH_ID_VALUE" }} +client_secret: {{ "OAUTH_SECRET_PLAIN_VALUE" }} +token_url: {{ "OAUTH_URL_VALUE" }} +{{- else -}} +client_id: {{ .Values.clientId | default (.Values.global.oauth).clientId | required ".clientId is required" }} +token_url: {{ .Values.tokenUrl | default (.Values.global.oauth).tokenUrl | required ".tokenUrl is required" }} +{{- if .Values.clientSecret }} +client_secret: {{ .Values.clientSecret }} +{{- else if .Values.clientSecretEnvVar }} +client_secret: "${APPD_OTELCOL_CLIENT_SECRET}" +{{- else if .Values.clientSecretVolume }} +client_secret: {{ (include "appdynamics-otel-collector.clientSecretVolumePath" .Values.clientSecretVolume) | toYaml }} +{{- else if (.Values.global.oauth).clientSecretEnvVar }} +client_secret: "${APPD_OTELCOL_CLIENT_SECRET}" +{{- else }} +client_secret: {{required ".clientSecret is required" (.Values.global.oauth).clientSecret}} +{{- end }} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.endpoint" -}} +{{- if .Values.global.smartAgentInstall -}} +{{ "SERVICE_DOMAIN_VALUE" }}/data +{{- else -}} +{{ .Values.endpoint | default (.Values.global.oauth).endpoint | required ".endpoint is required" }} +{{- end }} +{{- end }} + +{{/* + Generate the secret environment variable for OAuth2.0 + */}} +{{- define "appdynamics-otel-collector.clientSecretEnvVar" -}} +{{- if .Values.clientSecretEnvVar -}} +name: APPD_OTELCOL_CLIENT_SECRET +{{- .Values.clientSecretEnvVar | toYaml | nindent 0}} +{{- else if (.Values.global.oauth).clientSecretEnvVar -}} +{{- (.Values.global.oauth).clientSecretEnvVar | toYaml | nindent 0}} +{{- end }} +{{- end }} + +{{/* httpProxy */}} +{{- define "appdynamics-otel-collector.client.agent.proxy" -}} +{{- if .Values.global.smartAgentInstall -}} +agent_http_proxy: {{ "AGENT_HTTP_PROXY_VALUE" }} +agent_https_proxy: {{ "AGENT_HTTPS_PROXY_VALUE" }} +{{- else }} +{{ with .Values.global.agentManagementProxy -}} +agent_http_proxy: {{ .httpProxy }} +agent_https_proxy: {{ .httpsProxy }} +agent_no_proxy: {{- toYaml .noProxy | nindent 4 }} +{{- end }} +{{- end }} +{{- end }} + +{{/* tenant id extracted from token url or from smart agent directly*/}} +{{- define "appdynamics-otel-collector.tenant.id" -}} +{{- if .Values.global.smartAgentInstall -}} +{{ "OAUTH_TENANT_ID_VALUE" }} +{{- else -}} +{{- if .Values.tenantId -}} +{{ .Values.tenantId }} +{{- else -}} +{{- $tokenUrl := .Values.tokenUrl | default (.Values.global.oauth).tokenUrl | required ".tokenUrl is required" -}} +{{- $authTenantId := (regexFind "\\/auth\\/[0-9a-z\\-]{36}" $tokenUrl) -}} +{{- if eq (len $authTenantId) (add (len "/auth/") 36) -}} +{{ substr (len "/auth/") (len $authTenantId) $authTenantId }} +{{- else -}} +{{- required "Please provide tenantId." "" }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.serviceURL" -}} +{{- if .Values.global.smartAgentInstall -}} +{{ "SERVICE_URL_VALUE" }} +{{- else -}} +{{- $endpoint := (include "appdynamics-otel-collector.endpoint" .) -}} +{{ substr 0 (int (sub (len $endpoint) (len "/data"))) $endpoint }}/rest/agent/service +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_config-sampler.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_config-sampler.tpl new file mode 100644 index 00000000..b3da10ab --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_config-sampler.tpl @@ -0,0 +1,152 @@ +{{- define "appdynamics-otel-collector.tailsampler.loadbalancing" -}} +processors: + batch/traces: + send_batch_size: 100 # too large size very impact loadbalancing exporter performance +exporters: + loadbalancing: + routing_key: "traceID" + protocol: + otlp: + compression: none + tls: + insecure: true + retry_on_failure: + max_interval: 5s + resolver: + k8s: + service: {{ .Values.presets.tailsampler.service.name -}}.{{ include "appdynamics-otel-collector.namespace" .}} + ports: [24317] +service: + pipelines: + traces: + exporters: [loadbalancing] +{{- end}} + +{{- define "appdynamics-otel-collector.tailsampler.sampler" -}} +receivers: + otlp/groupedtraces: + protocols: + grpc: + endpoint: 0.0.0.0:24317 + http: + endpoint: 0.0.0.0:24318 +processors: +{{- $deploy_mode := split "_" .Values.presets.tailsampler.deploy_mode }} +{{- if eq $deploy_mode._0 "sidecar" }} + k8sattributes: + passthrough: false +{{- end}} + trace_classification_and_sampling: +{{- .Values.presets.tailsampler.trace_classification_and_sampling | toYaml | nindent 4 }} + consistent_proportional_sampler: +{{- .Values.presets.tailsampler.consistent_proportional_sampler | toYaml | nindent 4 }} + groupbyattrs/compact: + groupbytrace: +{{- .Values.presets.tailsampler.groupbytrace | toYaml | nindent 4 }} + intermediate_sampler: +{{- .Values.presets.tailsampler.intermediate_sampler | toYaml | nindent 4 }} + +service: + pipelines: + traces/sampler: + receivers: [otlp/groupedtraces] + processors: +{{- if eq $deploy_mode._0 "sidecar" }} +{{- .Values.presets.tailsampler.pipeline_sidecar_loadbalancer | toYaml | nindent 8}} +{{- else }} +{{- .Values.presets.tailsampler.pipeline | toYaml | nindent 8}} +{{- end}} + exporters: [otlphttp] +{{- end}} + +{{- define "appdynamics-otel-collector.tailsampler.tlsConfig.loadbalancing" -}} +{{- if .Values.global.tls.otelExporter.settings }} +exporters: + loadbalancing: + protocol: + otlp: + compression: none + tls: +{{- deepCopy .Values.global.tls.otelExporter.settings | toYaml | nindent 10}} +{{- end}} +{{- end}} + +{{- define "appdynamics-otel-collector.tailsampler.tlsConfig.tracegrouping" -}} +{{- if .Values.global.tls.otelReceiver.settings }} +receivers: + otlp/groupedtraces: + protocols: + grpc: + tls: +{{- deepCopy .Values.global.tls.otelReceiver.settings | toYaml | nindent 10}} + http: + tls: +{{- deepCopy .Values.global.tls.otelReceiver.settings | toYaml | nindent 10}} +{{- end}} +{{- end}} + +{{- define "appdynamics-otel-collector.tailsampler.samplingLoadBalancerDefaultPaths" -}} +{{- if .secret }} +{{ $path := .path | default "/etc/otel/certs/receiver"}} +{{- if .secret.secretKeys.caCert}} +ca_file: {{$path}}/{{.secret.secretKeys.caCert}} +{{- end}} +cert_file: {{$path}}/{{.secret.secretKeys.tlsCert}} +key_file: {{$path}}/{{.secret.secretKeys.tlsKey}} +{{- end}} +{{- end}} + +{{- define "appdynamics-otel-collector.tailsampler.tlsConfigFromSecrets.loadbalancing" -}} +{{- with .Values.global.tls.otelReceiver}} +{{- if .secret }} +exporters: + loadbalancing: + protocol: + otlp: + tls: +{{- (include "appdynamics-otel-collector.tailsampler.samplingLoadBalancerDefaultPaths" .) | nindent 10}} + insecure_skip_verify: true + insecure: false +{{- end}} +{{- end}} +{{- end}} + + +{{- define "appdynamics-otel-collector.tailsampler.tlsConfigFromSecrets.tracegrouping" -}} +{{- with .Values.global.tls.otelReceiver}} +receivers: + otlp/groupedtraces: + protocols: + grpc: + tls: +{{- (include "appdynamics-otel-collector.serverDefaultPaths" .) | nindent 10}} + http: + tls: +{{- (include "appdynamics-otel-collector.serverDefaultPaths" .) | nindent 10}} +{{- end}} +{{- end}} + +{{- define "appdynamics-otel-collector.presampler" -}} +{{- if .Values.presets.presampler.enable }} +processors: + consistent_proportional_sampler/presampler: +{{- .Values.presets.presampler.consistent_proportional_sampler | toYaml | nindent 4 }} + consistent_sampler/presampler: +{{- .Values.presets.presampler.consistent_sampler | toYaml | nindent 4 }} +service: + pipelines: + traces: + processors: +{{- if eq .Values.presets.presampler.deploy_mode "gateway"}} +{{- .Values.presets.presampler.pipeline | toYaml | nindent 8}} +{{- else }} +{{- .Values.presets.presampler.pipeline_sidecar | toYaml | nindent 8}} +{{- end }} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.samplerdebug" -}} +{{- if .Values.presets.samplerDebug.enable }} +{{- .Values.presets.samplerDebug.config | toYaml }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_helps.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_helps.tpl new file mode 100644 index 00000000..c34c2e28 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_helps.tpl @@ -0,0 +1,238 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "appdynamics-otel-collector.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* + Create a default fully qualified app name. + We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). + If release name contains chart name it will be used as a full name. +*/}} +{{- define "appdynamics-otel-collector.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* + Create a default fully qualified app name. + We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). + If release name contains chart name it will be used as a full name. +*/}} +{{- define "appdynamics-otel-collector.deployFullname" -}} +{{- if .var1.Values.fullnameOverride }} +{{- printf "%s%s-%s" .var1.Values.fullnameOverride .os .type | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .var1.Chart.Name .var1.Values.nameOverride }} +{{- if contains $name .var1.Release.Name }} +{{- printf "%s%s-%s" .var1.Release.Name .os .type | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s%s-%s-%s" .var1.Release.Name .os .type $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* + Create a default fully qualified app name for linux daemonset gateway. + */}} +{{- define "appdynamics-otel-collector.daemonset.fullname" -}} +{{ include "appdynamics-otel-collector.deployFullname" (dict "var1" . "os" "" "type" "ds") | trunc 42 | trimSuffix "-" }} +{{- end }} + +{{/* + Create a default fully qualified app name for daemonset gateway. + */}} +{{- define "appdynamics-otel-collector.daemonset.windows.fullname" -}} +{{ include "appdynamics-otel-collector.deployFullname" (dict "var1" . "os" "-win" "type" "ds") | trunc 42 | trimSuffix "-" }} +{{- end }} + + +{{/* + Create a default fully qualified app name for linux statefulset gateway. + */}} +{{- define "appdynamics-otel-collector.statefulset.fullname" -}} +{{ include "appdynamics-otel-collector.deployFullname" (dict "var1" . "os" "" "type" "ss") | trunc 42 | trimSuffix "-" }} +{{- end }} + +{{/* + Create a default fully qualified app name for statefulset gateway. + */}} +{{- define "appdynamics-otel-collector.statefulset.windows.fullname" -}} +{{ include "appdynamics-otel-collector.deployFullname" (dict "var1" . "os" "-win" "type" "ss") | trunc 42 | trimSuffix "-" }} +{{- end }} + +{{/* + Create a default fully qualified app name for linux sampler. +*/}} +{{- define "appdynamics-otel-collector.tailsampler.fullname" -}} +{{ include "appdynamics-otel-collector.deployFullname" (dict "var1" . "os" "" "type" "ts") | trunc 42 | trimSuffix "-" }} +{{- end }} + +{{/* + Create a default fully qualified app name for windows sampler. +*/}} +{{- define "appdynamics-otel-collector.tailsampler.windows.fullname" -}} +{{ include "appdynamics-otel-collector.deployFullname" (dict "var1" . "os" "-win" "type" "ts") | trunc 42 | trimSuffix "-" }} +{{- end }} + +{{/* + Create a default fully qualified app name for linux sampler. + */}} +{{- define "appdynamics-otel-collector.sidecar.fullname" -}} +{{ include "appdynamics-otel-collector.deployFullname" (dict "var1" . "os" "" "type" "sc") | trunc 42 | trimSuffix "-" }} +{{- end }} + +{{/* + Create a default fully qualified app name for windows sampler. + */}} +{{- define "appdynamics-otel-collector.sidecar.windows.fullname" -}} +{{ include "appdynamics-otel-collector.deployFullname" (dict "var1" . "os" "-win" "type" "sc") | trunc 42 | trimSuffix "-" }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "appdynamics-otel-collector.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +Open telemetry operator assigns recommended labels like "app.kubernetes.io/instance" automatically, to avoid conflict, +we change to to use app.appdynamics.otel.collector. +*/}} +{{- define "appdynamics-otel-collector.labels" -}} +helm.sh/chart: {{ include "appdynamics-otel-collector.chart" . }} +{{- if .Chart.AppVersion }} +app.appdynamics.otel.collector/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.appdynamics.otel.collector/managed-by: Helm +{{- end }} + +{{/* +Selector labels for all +*/}} +{{- define "appdynamics-otel-collector.selectorLabels" -}} +app.appdynamics.otel.collector/name: {{ include "appdynamics-otel-collector.name" . }} +app.appdynamics.otel.collector/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Selector labels for gateway +*/}} +{{- define "appdynamics-otel-collector.gateway.selectorLabels" -}} +{{- include "appdynamics-otel-collector.selectorLabels" . }} +{{- $deploy_mode := split "_" .Values.presets.tailsampler.deploy_mode }} +{{- if and .Values.presets.tailsampler.enable (eq $deploy_mode._1 "gateway")}} +app.appdynamics.otel.collector/tailsampler: "true" +{{- end }} +app.appdynamics.otel.collector/gateway: "true" +{{- end }} + +{{/* +Selector labels for daemonset +*/}} +{{- define "appdynamics-otel-collector.selectorLabelsDaemonset" -}} +{{- include "appdynamics-otel-collector.gateway.selectorLabels" . }} +app.appdynamics.otel.collector/mode: "daemonset" +{{- end }} + +{{/* +Selector labels for statefulset +*/}} +{{- define "appdynamics-otel-collector.selectorLabelsStatefulset" -}} +{{- include "appdynamics-otel-collector.gateway.selectorLabels" . }} +app.appdynamics.otel.collector/mode: "statefulset" +{{- end }} + +{{/* +Selector labels for sampler +*/}} +{{- define "appdynamics-otel-collector.tailsampler.selectorLabels" -}} +{{- include "appdynamics-otel-collector.selectorLabels" . }} +app.appdynamics.otel.collector/tailsampler: "true" +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "appdynamics-otel-collector.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "appdynamics-otel-collector.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account for target allocator to use +*/}} +{{- define "appdynamics-otel-collector.targetAllocatorServiceAccountName" -}} +{{- if .Values.targetAllocatorServiceAccount.create }} +{{- default (printf "%s%s" (include "appdynamics-otel-collector.fullname" .) "-target-allocator") .Values.targetAllocatorServiceAccount.name }} +{{- else }} +{{- default "default" .Values.targetAllocatorServiceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Merge labels from user inputs +*/}} +{{- define "appdynamics-otel-collector.finalLabelsDaemonset" -}} +{{- $labels := fromYaml (include "appdynamics-otel-collector.labels" .) -}} +{{- $labels := (include "appdynamics-otel-collector.selectorLabelsDaemonset" .) | fromYaml | mustMergeOverwrite $labels }} +{{- $labels := mustMergeOverwrite .Values.labels $labels -}} +{{ toYaml $labels }} +{{- end }} + +{{/* +Merge labels from user inputs +*/}} +{{- define "appdynamics-otel-collector.finalLabelsStatefulset" -}} +{{- $labels := fromYaml (include "appdynamics-otel-collector.labels" .) -}} +{{- $labels := (include "appdynamics-otel-collector.selectorLabelsStatefulset" .) | fromYaml | mustMergeOverwrite $labels }} +{{- $labels := mustMergeOverwrite .Values.labels $labels -}} +{{ toYaml $labels }} +{{- end }} + +{{/* + Merge labels from user inputs + */}} +{{- define "appdynamics-otel-collector.tailsampler.finalLabels" -}} +{{- $labels := fromYaml (include "appdynamics-otel-collector.labels" .) -}} +{{- $labels := (include "appdynamics-otel-collector.tailsampler.selectorLabels" .) | fromYaml | mustMergeOverwrite $labels }} +{{- $labels := mustMergeOverwrite $labels .Values.labels -}} +{{ toYaml $labels }} +{{- end }} + +{{/* +Generate agent management k8s deployment naming config +example input - (dict "var1" . "os" "win" "type" "ss") +*/}} +{{- define "appdynamics-otel-collector.agentManagementNameConfig" -}} +{{- if or .var1.Values.agentManagement .var1.Values.agentManagementSelfTelemetry }} +extensions: + appdagentmanagementextension: + deployment: + name: {{.name}}-collector +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.agentManagementModeConfig" -}} +{{- if or .var1.Values.agentManagement .var1.Values.agentManagementSelfTelemetry }} +extensions: + appdagentmanagementextension: + deployment: + type: {{.mode}} +{{- end }} +{{- end }} + diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_release-specific.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_release-specific.tpl new file mode 100644 index 00000000..ff0ccced --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_release-specific.tpl @@ -0,0 +1,7 @@ +{{- define "appdynamics-otel-collector.readClusterId" }} +{{- if (lookup "v1" "Namespace" "" "kube-system").metadata -}} +{{ required "Could not fetch kube-system uid to populate clusterID! " (lookup "v1" "Namespace" "" "kube-system").metadata.uid }} +{{- else -}} +{{ .Values.global.clusterId | required "clusterId needs to be specified when kube-system metadata is not accessible!" }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-daemonset.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-daemonset.tpl new file mode 100644 index 00000000..54b9696f --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-daemonset.tpl @@ -0,0 +1,186 @@ +{{- define "appdynamics-otel-collector-daemonset.filelog-receiver.basedefination" -}} +{{- if .var1.Values.enableFileLog }} +receivers: + filelog: + poll_interval: 10ms + include: {{ .var1.Values.filelogReceiverConfig.includeLogsPath }} + exclude: {{ .var1.Values.filelogReceiverConfig.excludeLogsPath }} + start_at: beginning + include_file_path: true + include_file_name: false + operators: + - type: router + id: get-format + routes: + - output: parser-docker + expr: 'body matches "^\\{"' + - type: json_parser + id: parser-docker + output: extract_metadata_from_filepath + timestamp: + parse_from: attributes.time + layout: '%Y-%m-%dT%H:%M:%S.%LZ' + - type: move + from: attributes.log + to: body + - type: regex_parser + id: extract_metadata_from_filepath + regex: '^.*\/(?P[^_]+)_(?P[^_]+)_(?P[a-f0-9\-]{36})\/(?P[^\._]+)\/(?P\d+)\.log$' + parse_from: attributes["log.file.path"] + - type: move + from: attributes.stream + to: attributes["log.iostream"] + - type: move + from: attributes.container_name + to: resource["k8s.container.name"] + - type: move + from: attributes.namespace + to: resource["k8s.namespace.name"] + - type: move + from: attributes.pod_name + to: resource["k8s.pod.name"] + - type: move + from: attributes.restart_count + to: resource["k8s.container.restart_count"] + - type: move + from: attributes.uid + to: resource["k8s.pod.uid"] +processors: + resource/filelog: + attributes: + - key: telemetry.sdk.name + action: upsert + value: "log-agent" + - key: k8s.cluster.id + action: upsert + value: {{ (include "appdynamics-otel-collector.clusterId" .var1) | quote}} + - key: source.name + action: upsert + value: "log-agent" + - key: k8s.cluster.name + action: upsert + value: {{ (include "appdynamics-otel-collector.cluster.name" .var1) | quote}} + - key: _message_parser.pattern + action: upsert + value: {{ .var1.Values.filelogReceiverConfig.messageParserPattern | quote }} + - key: _message_parser.type + action: upsert + value: {{ .var1.Values.filelogReceiverConfig.messageParserType | quote }} + - key: log_sender + action: upsert + value: "AppD_filelog_recevier" + - key: host.name + action: delete + - key: cloud.provider + action: delete + - key: cloud.platform + action: delete + - key: cloud.region + action: delete + - key: cloud.account.id + action: delete + - key: cloud.availability_zone + action: delete + - key: host.image.id + action: delete + - key: host.type + action: delete + - key: host.name + action: delete + resourcedetection: + detectors: ["ec2", "system"] + system: + hostname_sources: ["os", "cname", "lookup", "dns"] + transform/filelog: + log_statements: + - context: resource + statements: + - set(attributes["internal.container.encapsulating_object_id"],Concat([attributes["k8s.cluster.id"],attributes["k8s.pod.uid"]],":")) + k8sattributes/filelog: + auth_type: "serviceAccount" + passthrough: false + filter: + node_from_env_var: KUBE_NODE_NAME + extract: + metadata: + - k8s.pod.name + - k8s.pod.uid + - k8s.deployment.name + - k8s.namespace.name + - k8s.node.name + - k8s.pod.start_time + - container.id + pod_association: + - sources: + - from: resource_attribute + name: k8s.pod.uid +service: + pipelines: + logs/filelog: + receivers: [filelog] + processors: ["memory_limiter","k8sattributes/filelog", "resourcedetection", "resource/filelog","transform/filelog"] + exporters: [logging, otlphttp] +{{- end }} +{{- end }} + +{{/* + daemonset config + var1 - global scope + var2 - computed spec +*/}} +{{- define "appdynamics-otel-collector-daemonset.autoValueConfig" -}} +{{- $mergedConfig := (include "appdynamics-otel-collector.autoValueConfig" . | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector-daemonset.filelog-receiver.basedefination" . | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementModeConfig" (dict "mode" "daemonset" "var1" .var1) | fromYaml ) }} +{{- if .var1.Values.mode.daemonset.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .var1.Values.mode.daemonset.configOverride)}} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + +{{- define "appdynamics-otel-collector-daemonset.valueVarLogVolumeMounts" -}} +name: {{.name}} +mountPath: {{.mountPath}} +{{- end }} +{{- define "appdynamics-otel-collector-daemonset.valueVarLogVolume" -}} +name: {{.name}} +hostPath: + path: {{.path}} +{{- end }} + +{{- define "appdynamics-otel-collector-daemonset.valueVarLogVolumeSpec" -}} +{{- if .Values.enableFileLog }} +podSecurityContext: + runAsUser: 10001 + runAsGroup: 0 +{{- $specVolumeMounts := get .spec "volumeMounts" | deepCopy }} +{{- if not $specVolumeMounts }} +{{- $specVolumeMounts = list }} +{{- end }} +{{- $specVolumeMounts = append $specVolumeMounts (include "appdynamics-otel-collector-daemonset.valueVarLogVolumeMounts" (dict "name" "varlog" "mountPath" "/var/log") | fromYaml)}} +{{- $specVolumeMounts = append $specVolumeMounts (include "appdynamics-otel-collector-daemonset.valueVarLogVolumeMounts" (dict "name" "varlibdockercontainers" "mountPath" " /var/lib/docker/containers") | fromYaml)}} +volumeMounts: +{{- $specVolumeMounts | toYaml | nindent 2}} + +{{- $specVolume := get .spec "volumes" | deepCopy }} +{{- if not $specVolume }} +{{- $specVolume = list }} +{{- end }} +{{- $specVolume = append $specVolume (include "appdynamics-otel-collector-daemonset.valueVarLogVolume" (dict "name" "varlog" "path" "/var/log") | fromYaml)}} +{{- $specVolume = append $specVolume (include "appdynamics-otel-collector-daemonset.valueVarLogVolume" (dict "name" "varlibdockercontainers" "path" "/var/lib/docker/containers") | fromYaml)}} +volumes: +{{- $specVolume | toYaml | nindent 2}} +{{- end }} +{{- end }} + +{{/* + daemonset spec +*/}} +{{- define "appdynamics-otel-collector-daemonset.spec" -}} +{{- $spec := (include "appdynamics-otel-collector.spec" . | fromYaml) }} +{{- $spec := include "appdynamics-otel-collector-daemonset.valueVarLogVolumeSpec" (dict "Values" .Values "spec" $spec) | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $config := include "appdynamics-otel-collector-daemonset.autoValueConfig" (dict "var1" . "var2" $spec) | deepCopy | fromYaml }} +{{- $spec := include "appdynamics-otel-collector.configToYamlString" $config | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := .Values.mode.daemonset.spec | deepCopy | mustMergeOverwrite $spec }} +{{- toYaml $spec }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-linux.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-linux.tpl new file mode 100644 index 00000000..684d9dbf --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-linux.tpl @@ -0,0 +1,67 @@ +{{/* + daemonset linux config + var1 - global scope + var2 - computed spec +*/}} +{{- define "appdynamics-otel-collector-daemonset-linux.autoValueConfig" -}} +{{- $mergedConfig := (include "appdynamics-otel-collector-daemonset.autoValueConfig" . | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementNameConfig" (dict "name" (include "appdynamics-otel-collector.daemonset.fullname" .var1) "var1" .var1) | fromYaml ) }} +{{- with .var1.Values.env.linux.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .) }} +{{- end }} +{{- with ((.var1.Values.env.linux.mode).daemonset).configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .) }} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + + +{{/* + daemonset linux spec +*/}} +{{- define "appdynamics-otel-collector-daemonset-linux.spec" -}} +{{- $spec := (include "appdynamics-otel-collector-daemonset.spec" . | fromYaml) }} +{{- if .Values.env.linux.spec -}} +{{- $spec := .Values.env.linux.spec | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- with ((.Values.env.linux.mode).daemonset).spec }} +{{- $spec := . | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- $config := include "appdynamics-otel-collector-daemonset-linux.autoValueConfig" (dict "var1" . "var2" $spec) | deepCopy | fromYaml }} +{{- $spec := include "appdynamics-otel-collector.configToYamlString" $config | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- toYaml $spec }} +{{- end }} + + +{{/* + statefulset linux config + var1 - global scope + var2 - computed spec +*/}} +{{- define "appdynamics-otel-collector-statefulset-linux.autoValueConfig" -}} +{{- $mergedConfig := (include "appdynamics-otel-collector-statefulset.autoValueConfig" . | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementNameConfig" (dict "name" (include "appdynamics-otel-collector.statefulset.fullname" .var1) "var1" .var1) | fromYaml ) }} +{{- with .var1.Values.env.linux.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .) }} +{{- end }} +{{- with ((.var1.Values.env.linux.mode).statefulset).configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .) }} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + +{{/* + statefulset linux spec +*/}} +{{- define "appdynamics-otel-collector-statefulset-linux.spec" -}} +{{- $spec := (include "appdynamics-otel-collector-statefulset.spec" . | fromYaml) }} +{{- $config := include "appdynamics-otel-collector-statefulset-linux.autoValueConfig" (dict "var1" . "var2" $spec) | deepCopy | fromYaml }} +{{- $spec := include "appdynamics-otel-collector.configToYamlString" $config | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- if .Values.env.linux.spec -}} +{{- $spec := .Values.env.linux.spec | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- with ((.Values.env.linux.mode).statefulset).spec }} +{{- $spec := . | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- toYaml $spec }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-sidecar.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-sidecar.tpl new file mode 100644 index 00000000..91103853 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-sidecar.tpl @@ -0,0 +1,74 @@ +{{- define "appdynamics-otel-collector.sidecar.clientSideBalancing" -}} +{{- if .Values.presets.multi_tier.sidecar.client_side_loadbalancing }} +exporters: + otlp: + endpoint: dns:///appdynamics-otel-collector-service-headless.{{ include "appdynamics-otel-collector.namespace" .}}.svc.cluster.local:4317 + balancer_name: round_robin + tls: + insecure: true +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.sidecar.selfTelemetryOverride" -}} +{{- if .Values.selfTelemetry }} +processors: + batch/self: + send_batch_size: 100 + timeout: 1s +service: + pipelines: + metrics/self: + exporters: [otlp] +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.sidecar.autoValueConfig" -}} +{{- $mergedConfig := tpl (get .var1.Values.presets.multi_tier.sidecar "config" | deepCopy | toYaml) .var1 | fromYaml}} +{{- if eq .var1.Values.presets.presampler.deploy_mode "sidecar"}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.presampler" .var1 | fromYaml )}} +{{- end }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.samplerdebug" .var1 | fromYaml )}} +{{- $deploy_mode := split "_" .var1.Values.presets.tailsampler.deploy_mode }} +{{- if and .var1.Values.presets.tailsampler.enable (eq $deploy_mode._0 "sidecar")}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.loadbalancing" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.tlsConfig.loadbalancing" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.tlsConfigFromSecrets.loadbalancing" .var1 | fromYaml )}} +{{- end }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.memoryLimiter" .var2.resources.limits | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.selfTelemetry" (dict "var1" .var1 "var2" "appd-otel-col-sidecar") | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.sidecar.selfTelemetryOverride" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.traceContextPropagation" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.chartInfo" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.sidecar.clientSideBalancing" .var1 | fromYaml ) }} +{{- $mergedConfig := tpl ($mergedConfig | toYaml) .var1 | fromYaml }} +{{- if .var1.Values.presets.multi_tier.sidecar.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .var1.Values.presets.multi_tier.sidecar.configOverride)}} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + +{{- define "appdynamics-otel-collector.sidecar.spec" -}} +{{- $spec := .Values.presets.multi_tier.sidecar.spec | deepCopy }} +{{- $spec := include "appdynamics-otel-collector.valueTLSVolume" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := include "appdynamics-otel-collector.valueServiceAccount" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $config := include "appdynamics-otel-collector.sidecar.autoValueConfig" (dict "var1" . "var2" $spec) | deepCopy | fromYaml }} +{{- $spec := include "appdynamics-otel-collector.selfTelemetry.spec" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := include "appdynamics-otel-collector.configToYamlString" $config | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- toYaml $spec }} +{{- end }} + +{{- define "appdynamics-otel-collector.sidecar.linux.spec" -}} +{{- $spec := (include "appdynamics-otel-collector.sidecar.spec" . | fromYaml) }} +{{- if .Values.presets.multi_tier.sidecar.env.linux.spec -}} +{{- $spec := .Values.presets.multi_tier.sidecar.env.linux.spec | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- toYaml $spec }} +{{- end }} + +{{- define "appdynamics-otel-collector.sidecar.windows.spec" -}} +{{- $spec := (include "appdynamics-otel-collector.sidecar.spec" . | fromYaml) }} +{{- if .Values.presets.multi_tier.sidecar.env.windows.spec -}} +{{- $spec := .Values.presets.multi_tier.sidecar.env.windows.spec | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- toYaml $spec }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-statefulset.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-statefulset.tpl new file mode 100644 index 00000000..cd8d5840 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-statefulset.tpl @@ -0,0 +1,140 @@ +{{/* + Prometheus config +*/}} +{{- define "appdynamics-otel-collector-statefulset.prometheusConfig" -}} +{{- if .Values.enablePrometheus }} +receivers: + prometheus: + config: + scrape_configs: + - job_name: 'prometheus-exporter-endpoints' + scrape_interval: 60s + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_appdynamics_com_exporter_type] + action: keep + regex: (redis|kafka|kafkajmx) + replacement: $$1 + - source_labels: [__meta_kubernetes_endpoint_ready] + action: keep + regex: (.+) + replacement: $$1 + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + replacement: $$1 + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $$1:$$2 + - source_labels: [__meta_kubernetes_service_annotation_appdynamics_com_exporter_type] + action: replace + target_label: appdynamics_exporter_type + replacement: $$1 + - source_labels: [__meta_kubernetes_service_annotation_appdynamics_com_kafka_cluster_name] + action: replace + target_label: kafka_cluster_name + replacement: $$1 + + metric_relabel_configs: + - source_labels: [__name__] + regex: "kafka_(.+)|java_(.+)|redis_blocked_clients|redis_commands_duration_seconds_total|redis_commands_processed_total|redis_commands_total|redis_config_maxclients|redis_connected_clients|redis_connected_slave(.+)|redis_connections_received_total|redis_cpu_sys_children_seconds_total|redis_cpu_sys_seconds_total|redis_cpu_user_children_seconds_total|redis_cpu_user_seconds_total|redis_db_(.+)|redis_(.+)_keys_total|redis_instance_info|redis_keyspace_(.+)|redis_master_last_io_seconds_ago|redis_master_link_up|redis_master_sync_in_progress|redis_mem_fragmentation_ratio|redis_memory_max_bytes|redis_memory_used_bytes|redis_memory_used_dataset_bytes|redis_memory_used_lua_bytes|redis_memory_used_overhead_bytes|redis_memory_used_scripts_bytes|redis_net_(.+)|redis_pubsub_(.+)|redis_rdb_changes_since_last_save|redis_rdb_last_save_timestamp_seconds|redis_rejected_connections_total|redis_slave_info|redis_slowlog_length|redis_up(.*)" + action: keep + - source_labels: [__name__] + regex: "kafka_exporter_build_info|kafka_consumergroup_current_offset|kafka_consumergroup_lag|kafka_topic_partition_current_offset|kafka_topic_partition_in_sync_replica|kafka_topic_partition_leader|kafka_topic_partition_leader_is_preferred|kafka_topic_partition_oldest_offset" + action: drop + +processors: + groupbyattrs/prometheus: + keys: + - appdynamics_exporter_type + resource/prometheus: + attributes: + - key: telemetry.sdk.name + value: "prometheus" + action: upsert + - key: prometheus.exporter_type + from_attribute: appdynamics_exporter_type + action: upsert + - key: appdynamics_exporter_type + action: delete + - key: k8s.cluster.name + value: {{ (include "appdynamics-otel-collector.cluster.name" .) | quote}} + action: upsert + - key: k8s.cluster.id + value: {{ (include "appdynamics-otel-collector.clusterId" .) | quote}} + action: upsert + metricstransform/prometheus: + transforms: + - include: kafka_log_log_size + match_type: strict + action: update + operations: + - action: aggregate_labels + label_set: [ kafka_cluster_name,topic ] + aggregation_type: sum + - include: kafka_topic_partition_replicas + match_type: strict + action: update + operations: + - action: aggregate_labels + label_set: [ kafka_cluster_name,topic ] + aggregation_type: sum + - include: kafka_topic_partition_under_replicated_partition + match_type: strict + action: update + operations: + - action: aggregate_labels + label_set: [ kafka_cluster_name,topic ] + aggregation_type: sum + +service: + pipelines: + metrics/prometheus: + receivers: [ prometheus ] + processors: [ memory_limiter, groupbyattrs/prometheus, resource/prometheus, metricstransform/prometheus, batch ] + exporters: [ otlphttp ] +{{- end }} +{{- end }} + +{{/* + Spec changes for Prometheus config +*/}} +{{- define "appdynamics-otel-collector-statefulset.prometheusSpec" -}} +{{- if .Values.enablePrometheus -}} +targetAllocator: + enabled: true + serviceAccount: {{ include "appdynamics-otel-collector.valueTargetAllocatorServiceAccount" . }} +{{- end }} +{{- end }} + +{{/* + statefulset config + var1 - global scope + var2 - computed spec +*/}} +{{- define "appdynamics-otel-collector-statefulset.autoValueConfig" -}} +{{- $mergedConfig := (include "appdynamics-otel-collector.autoValueConfig" . | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector-statefulset.prometheusConfig" .var1 | fromYaml) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementModeConfig" (dict "mode" "statefulset" "var1" .var1) | fromYaml) }} +{{- if .var1.Values.mode.statefulset.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .var1.Values.mode.statefulset.configOverride) }} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + +{{/* + statefulset spec +*/}} +{{- define "appdynamics-otel-collector-statefulset.spec" -}} +{{- $spec := (include "appdynamics-otel-collector.spec" . | fromYaml) }} +{{- $spec := include "appdynamics-otel-collector-statefulset.prometheusSpec" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $config := include "appdynamics-otel-collector-statefulset.autoValueConfig" (dict "var1" . "var2" $spec) | deepCopy | fromYaml }} +{{- $spec := include "appdynamics-otel-collector.configToYamlString" $config | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := .Values.mode.statefulset.spec | deepCopy | mustMergeOverwrite $spec }} +{{- toYaml $spec }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-tailsampler.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-tailsampler.tpl new file mode 100644 index 00000000..055cc824 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-tailsampler.tpl @@ -0,0 +1,84 @@ +{{- define "appdynamics-otel-collector.tailsampler.autoValueConfig" -}} +{{- $otelConfig := tpl (get .var1.Values.presets.multi_tier.tailsampler "config" | deepCopy | toYaml) .var1 | fromYaml}} +{{- $mergedConfig := mustMergeOverwrite $otelConfig (include "appdynamics-otel-collector.derivedConfig" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.samplerdebug" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.sampler" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.tlsConfig.tracegrouping" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.tlsConfigFromSecrets.tracegrouping" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.memoryLimiter" .var2.resources.limits | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.selfTelemetry" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagement" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementSelfTelemetry" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.traceContextPropagation" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.chartInfo" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementModeConfig" (dict "mode" "deployment" "var1" .var1) | fromYaml ) }} +{{- $mergedConfig := tpl ($mergedConfig | toYaml) .var1 | fromYaml }} +{{- if .var1.Values.presets.multi_tier.tailsampler.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .var1.Values.presets.multi_tier.tailsampler.configOverride)}} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + +{{/* + Set service.ports into spec.ports in the value file. + If the spec.ports is already set, the service.ports section won't take any effect. +*/}} +{{- define "appdynamics-otel-collector.tailsampler.valueServicePorts" -}} +{{- if not .Values.presets.multi_tier.tailsampler.spec.ports }} +ports: +{{- .Values.presets.tailsampler.service.ports | toYaml | nindent 2}} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.tailsampler.linux.autoValueConfig" -}} +{{- $mergedConfig := (include "appdynamics-otel-collector.tailsampler.autoValueConfig" . | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementNameConfig" (dict "name" (include "appdynamics-otel-collector.tailsampler.fullname" .var1) "var1" .var1) | fromYaml ) }} +{{- with .var1.Values.presets.multi_tier.tailsampler.env.linux.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .) }} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + +{{- define "appdynamics-otel-collector.tailsampler.replicas" -}} +replicas: {{ .Values.presets.tailsampler.replicas }} +{{- end }} + +{{- define "appdynamics-otel-collector.tailsampler.spec" -}} +{{- $spec := .Values.presets.multi_tier.tailsampler.spec | deepCopy }} +{{- $spec := include "appdynamics-otel-collector.tailsampler.replicas" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := include "appdynamics-otel-collector.appendEnv" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := include "appdynamics-otel-collector.valuesVolume" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := include "appdynamics-otel-collector.tailsampler.valueServicePorts" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := include "appdynamics-otel-collector.valueServiceAccount" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := include "appdynamics-otel-collector.selfTelemetry.spec" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- toYaml $spec }} +{{- end }} + +{{- define "appdynamics-otel-collector.tailsampler.linux.spec" -}} +{{- $spec := (include "appdynamics-otel-collector.tailsampler.spec" . | fromYaml) }} +{{- if .Values.presets.multi_tier.tailsampler.env.linux.spec -}} +{{- $spec := .Values.presets.multi_tier.tailsampler.env.linux.spec | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- $config := include "appdynamics-otel-collector.tailsampler.linux.autoValueConfig" (dict "var1" . "var2" $spec) | deepCopy | fromYaml }} +{{- $spec := include "appdynamics-otel-collector.configToYamlString" $config | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- toYaml $spec }} +{{- end }} + +{{- define "appdynamics-otel-collector.tailsampler.windows.autoValueConfig" -}} +{{- $mergedConfig := (include "appdynamics-otel-collector.tailsampler.autoValueConfig" . | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementNameConfig" (dict "name" (include "appdynamics-otel-collector.tailsampler.windows.fullname" .var1) "var1" .var1) | fromYaml ) }} +{{- with .var1.Values.presets.multi_tier.tailsampler.env.windows.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .) }} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + +{{- define "appdynamics-otel-collector.tailsampler.windows.spec" -}} +{{- $spec := (include "appdynamics-otel-collector.tailsampler.spec" . | fromYaml) }} +{{- if .Values.presets.multi_tier.tailsampler.env.windows.spec -}} +{{- $spec := .Values.presets.multi_tier.tailsampler.env.windows.spec | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- $config := include "appdynamics-otel-collector.tailsampler.windows.autoValueConfig" (dict "var1" . "var2" $spec) | deepCopy | fromYaml }} +{{- $spec := include "appdynamics-otel-collector.configToYamlString" $config | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- toYaml $spec }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-windows.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-windows.tpl new file mode 100644 index 00000000..93aa0d09 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-windows.tpl @@ -0,0 +1,67 @@ +{{/* + daemonset windows config + @param .var1 global scope + @param .var2 computed spec +*/}} +{{- define "appdynamics-otel-collector-daemonset-windows.autoValueConfig" -}} +{{- $mergedConfig := (include "appdynamics-otel-collector-daemonset.autoValueConfig" . | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementNameConfig" (dict "name" (include "appdynamics-otel-collector.daemonset.windows.fullname" .var1) "var1" .var1) | fromYaml ) }} +{{- with .var1.Values.env.windows.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .) }} +{{- end }} +{{- with ((.var1.Values.env.windows.mode).daemonset).configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .) }} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + + +{{/* + daemonset windows spec +*/}} +{{- define "appdynamics-otel-collector-daemonset-windows.spec" -}} +{{- $spec := include "appdynamics-otel-collector-daemonset.spec" . | fromYaml }} +{{- if .Values.env.windows.spec -}} +{{- $spec := .Values.env.windows.spec | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- with ((.Values.env.windows.mode).daemonset).spec }} +{{- $spec := . | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- $config := (include "appdynamics-otel-collector-daemonset-windows.autoValueConfig" (dict "var1" . "var2" $spec)) | deepCopy | fromYaml }} +{{- $spec := include "appdynamics-otel-collector.configToYamlString" $config | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- toYaml $spec }} +{{- end }} + + +{{/* + statefulset windows config + @param .var1 global scope + @param .var2 computed spec +*/}} +{{- define "appdynamics-otel-collector-statefulset-windows.autoValueConfig" -}} +{{- $mergedConfig := (include "appdynamics-otel-collector-statefulset.autoValueConfig" . | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementNameConfig" (dict "name" (include "appdynamics-otel-collector.statefulset.windows.fullname" .var1) "var1" .var1) | fromYaml ) }} +{{- with .var1.Values.env.windows.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .) }} +{{- end }} +{{- with ((.var1.Values.env.windows.mode).statefulset).configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .) }} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + +{{/* + statefulset windows spec +*/}} +{{- define "appdynamics-otel-collector-statefulset-windows.spec" -}} +{{- $spec := (include "appdynamics-otel-collector-statefulset.spec" . | fromYaml) }} +{{- $config := include "appdynamics-otel-collector-statefulset-windows.autoValueConfig" (dict "var1" . "var2" $spec) | deepCopy | fromYaml }} +{{- $spec := include "appdynamics-otel-collector.configToYamlString" $config | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- if .Values.env.windows.spec -}} +{{- $spec := .Values.env.windows.spec | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- with ((.Values.env.windows.mode).statefulset).spec }} +{{- $spec := . | deepCopy | mustMergeOverwrite $spec }} +{{- end }} +{{- toYaml $spec }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec.tpl new file mode 100644 index 00000000..460a9033 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec.tpl @@ -0,0 +1,652 @@ +{{/* + Derived configuation from top level properties +*/}} +{{/* + downward api environment variable + https://kubernetes.io/docs/concepts/workloads/pods/downward-api/ + params + envName - environment variable name + path - field path +*/}} +{{- define "appdynamics-otel-collector.downwardEnvVar" -}} +name: {{.envName}} +valueFrom: + fieldRef: + fieldPath: {{.path}} +{{- end }} + +{{- define "appdynamics-otel-collector.derivedConfig" -}} +extensions: + oauth2client: +{{- (include "appdynamics-otel-collector.derivedOAuth" .) | nindent 4}} +exporters: + otlphttp: + metrics_endpoint: {{ include "appdynamics-otel-collector.endpoint" . }}/v1/metrics + traces_endpoint: {{ include "appdynamics-otel-collector.endpoint" . }}/v1/trace + logs_endpoint: {{ include "appdynamics-otel-collector.endpoint" . }}/v1/logs + retry_on_failure: + max_elapsed_time: 180s +{{- end }} + +{{- define "appdynamics-otel-collector.tlsConfig" -}} +{{- if .Values.global.tls.otelReceiver.settings }} +receivers: + otlp: + protocols: + grpc: + tls: +{{- deepCopy .Values.global.tls.otelReceiver.settings | toYaml | nindent 10}} + http: + tls: +{{- deepCopy .Values.global.tls.otelReceiver.settings | toYaml | nindent 10}} + otlp/lca: + protocols: + grpc: + tls: +{{- deepCopy .Values.global.tls.otelReceiver.settings | toYaml | nindent 10}} + http: + tls: +{{- deepCopy .Values.global.tls.otelReceiver.settings | toYaml | nindent 10}} +{{- end }} +{{- if .Values.global.tls.otelExporter.settings }} +extensions: + oauth2client: + tls: +{{- deepCopy .Values.global.tls.otelExporter.settings | toYaml | nindent 6}} +exporters: + otlphttp: + tls: +{{- deepCopy .Values.global.tls.otelExporter.settings | toYaml | nindent 6}} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.traceContextPropagation" -}} +{{- if .Values.traceContextPropagation }} +service: + telemetry: + traces: + propagators: + - tracecontext +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.selfTelemetry" -}} +{{- if .Values.selfTelemetry }} +receivers: + prometheus/self: + config: + scrape_configs: + - job_name: {{ .Values.selfTelemetryServiceName | default "appd-otel-collector" | quote }} + scrape_interval: 60s + static_configs: + - targets: ["localhost:8888"] +exporters: + logging: + verbosity: detailed +processors: + batch/self: + transform/self: + metric_statements: + - context: resource + statements: + - set(attributes["prometheus.targets"],attributes["service.instance.id"]) where attributes["prometheus.targets"] == nil + - set(attributes["service.namespace"], "otelcol") + - set(attributes["otel.collector.description"], "AppDynamics Distribution of OpenTelemetry collector.") + - set(attributes["service.version"],attributes["service_version"]) + - set(attributes["telemetry.sdk.name"],"opentelemetry") + - set(attributes["k8s.pod.uid"], "${POD_UID}" ) + - set(attributes["k8s.cluster.name"], "test-cluster") + - context: datapoint + statements: + - set(resource.attributes["service.instance.id"],attributes["service_instance_id"]) + {{- if .Values.setPodUID }} + - set(resource.attributes["k8s.pod.uid"], "${POD_UID}" ) + {{- end }} + - set(resource.attributes["k8s.cluster.name"], {{ include "appdynamics-otel-collector.cluster.name" . | quote }}) + - set(resource.attributes["k8s.cluster.id"], {{ include "appdynamics-otel-collector.clusterId" . | quote}}) +service: + pipelines: + metrics/self: + receivers: [prometheus/self] + processors: [ memory_limiter, transform/self, batch/self] + exporters: [otlphttp] +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.agentManagement" -}} +{{- if or .Values.agentManagement .Values.agentManagementSelfTelemetry }} +extensions: + appdagentmanagementextension: + service_url: {{ include "appdynamics-otel-collector.serviceURL" . }} + agent_descriptor_type: "otel_collector" + agent_namespace: "otelcollector" + agent_name: {{.Release.Name}} + node_config: + node_name: "$NODE_NAME" + disable_opamp: {{.Values.disableOpamp}} + oauth: + {{- (include "appdynamics-otel-collector.derivedOAuth" .) | nindent 6}} + tenant_id: {{ include "appdynamics-otel-collector.tenant.id" . }} + platform: + id: {{ (include "appdynamics-otel-collector.clusterId" .) | quote }} + name: {{ (include "appdynamics-otel-collector.cluster.name" .) | quote }} + type: k8s + deployment: + scope: {{ include "appdynamics-otel-collector.namespace" .}} + unit: "${POD_NAME}" + unique: false + helm_chart_version: {{ .Values.global.helmChartVersion }} + http_client_settings: + {{- (include "appdynamics-otel-collector.client.agent.proxy" .) | nindent 6}} +service: + extensions: [health_check, oauth2client, appdagentmanagementextension] +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.agentManagementSelfTelemetry" -}} +{{- if .Values.agentManagementSelfTelemetry }} +receivers: + prometheus/self: + config: + scrape_configs: + - job_name: {{ .Values.selfTelemetryServiceName | default "appd-otel-collector" | quote }} + scrape_interval: 60s + static_configs: + - targets: ["localhost:8888"] + +processors: + batch/self: + agentmanagementresource: + appd_agent_management_ext: appdagentmanagementextension + resource: + "service.name": "" + "service.instance.id": "" + "net.host.port": "" + "http.scheme": "" + "telemetry.sdk.name": opentelemetry + "service_name": "" + "service_instance_id": "" + "service_version": "" + +exporters: +{{- .Values.presets.selfTelemetry.exporters | toYaml | nindent 2}} + +service: + pipelines: + metrics/agent_management_self_telemetry: + receivers: [prometheus/self] + processors: [memory_limiter, agentmanagementresource, batch/self] +{{- $exporter_list := list }} +{{- range $k,$v:= $.Values.presets.selfTelemetry.exporters }} +{{- $exporter_list = append $exporter_list $k }} +{{- end }} + exporters: +{{- $exporter_list | toYaml | nindent 8}} + +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.networkMonitoring" -}} +receivers: + otlp/ebpf: + protocols: + grpc: + endpoint: 0.0.0.0:24317 + http: + endpoint: 0.0.0.0:24318 +processors: + resource/ebpf: + attributes: + - key: telemetry.sdk.name + value: agent:otelnet_collector:collector + action: upsert + - key: netperf.platform.id + action: upsert + value: {{ include "appdynamics-otel-collector.clusterId" . | quote}} + - key: netperf.platform.type + action: upsert + value: k8s + filter/ebpf: + metrics: + metric: + - 'not (HasAttrOnDatapoint("source.resolution_type", "K8S_CONTAINER") or HasAttrOnDatapoint("dest.resolution_type", "K8S_CONTAINER"))' + metricstransform/ebpf: + transforms: + - include: tcp.bytes + action: insert + new_name: dummy.endpoint.bytes + operations: + - action: update_label + label: source.workload.name + new_label: source.endpoint.name + - include: udp.bytes + action: insert + new_name: dummy.endpoint.bytes + operations: + - action: update_label + label: source.workload.name + new_label: source.endpoint.name + attributes/ebpf: + actions: + - key: source.availability_zone + action: delete + - key: dest.availability_zone + action: delete + - key: az_equal + action: delete + - key: sf_product + action: delete + - key: source.environment + action: delete + - key: dest.environment + action: delete +service: + pipelines: + metrics/ebpf: + receivers: [otlp/ebpf] + processors: [memory_limiter, resource/ebpf, filter/ebpf, metricstransform/ebpf, attributes/ebpf, batch/metrics] + exporters: [otlphttp] +{{- end }} + +{{- define "appdynamics-otel-collector.chartInfo" -}} +{{- if .Values.sendChartInfo }} +exporters: + otlphttp: + headers: + appd-collector-helm-chart-version: "{{ tpl .Chart.Version . }}" + appd-collector-helm-chart-name: "{{ tpl .Chart.Name . }}" +{{- end }} +{{- end }} + +{{/* + Default memory limiter configuration for appdynamics-otel-collector based on k8s resource limits. +*/}} +{{- define "appdynamics-otel-collector.memoryLimiter" -}} +processors: + memory_limiter: +# check_interval is the time between measurements of memory usage. + check_interval: 5s +# By default limit_mib is set to 80% of ".Values.spec.resources.limits.memory" + limit_mib: {{ include "appdynamics-otel-collector.getMemLimitMib" .memory }} +# By default spike_limit_mib is set to 25% of ".Values.spec.resources.limits.memory" + spike_limit_mib: {{ include "appdynamics-otel-collector.getMemSpikeLimitMib" .memory }} +{{- end }} + +{{/* +Get memory_limiter limit_mib value based on 80% of resources.limits.memory. +*/}} +{{- define "appdynamics-otel-collector.getMemLimitMib" -}} +{{- div (mul (include "appdynamics-otel-collector.convertMemToMib" .) 80) 100 }} +{{- end -}} + +{{/* +Get memory_limiter spike_limit_mib value based on 25% of resources.limits.memory. +*/}} +{{- define "appdynamics-otel-collector.getMemSpikeLimitMib" -}} +{{- div (mul (include "appdynamics-otel-collector.convertMemToMib" .) 25) 100 }} +{{- end -}} + +{{/* +Convert memory value from resources.limit to numeric value in MiB to be used by otel memory_limiter processor. +*/}} +{{- define "appdynamics-otel-collector.convertMemToMib" -}} +{{- $mem := lower . -}} +{{- if hasSuffix "e" $mem -}} +{{- trimSuffix "e" $mem | atoi | mul 1000 | mul 1000 | mul 1000 | mul 1000 -}} +{{- else if hasSuffix "ei" $mem -}} +{{- trimSuffix "ei" $mem | atoi | mul 1024 | mul 1024 | mul 1024 | mul 1024 -}} +{{- else if hasSuffix "p" $mem -}} +{{- trimSuffix "p" $mem | atoi | mul 1000 | mul 1000 | mul 1000 -}} +{{- else if hasSuffix "pi" $mem -}} +{{- trimSuffix "pi" $mem | atoi | mul 1024 | mul 1024 | mul 1024 -}} +{{- else if hasSuffix "t" $mem -}} +{{- trimSuffix "t" $mem | atoi | mul 1000 | mul 1000 -}} +{{- else if hasSuffix "ti" $mem -}} +{{- trimSuffix "ti" $mem | atoi | mul 1024 | mul 1024 -}} +{{- else if hasSuffix "g" $mem -}} +{{- trimSuffix "g" $mem | atoi | mul 1000 -}} +{{- else if hasSuffix "gi" $mem -}} +{{- trimSuffix "gi" $mem | atoi | mul 1024 -}} +{{- else if hasSuffix "m" $mem -}} +{{- div (trimSuffix "m" $mem | atoi | mul 1000) 1024 -}} +{{- else if hasSuffix "mi" $mem -}} +{{- trimSuffix "mi" $mem | atoi -}} +{{- else if hasSuffix "k" $mem -}} +{{- div (trimSuffix "k" $mem | atoi) 1000 -}} +{{- else if hasSuffix "ki" $mem -}} +{{- div (trimSuffix "ki" $mem | atoi) 1024 -}} +{{- else -}} +{{- div (div ($mem | atoi) 1024) 1024 -}} +{{- end -}} +{{- end -}} + +{{- define "appdynamics-otel-collector.nonAppDTransformConfig" -}} +processors: + transform/logs: + log_statements: + - context: resource + statements: + - set(attributes["k8s.cluster.id"], {{ (include "appdynamics-otel-collector.clusterId" .) | quote}}) + - set(attributes["internal.container.encapsulating_object_id"],Concat([attributes["k8s.cluster.id"],attributes["k8s.pod.uid"]],":")) + k8sattributes/logs: + passthrough: false + extract: + metadata: + - k8s.pod.name + - k8s.pod.uid + - k8s.deployment.name + - k8s.namespace.name + - k8s.node.name + - k8s.pod.start_time + - container.id + - k8s.container.name + - container.image.name + - container.image.tag +{{- end}} + +{{/* + Append auto generated env to spec +*/}} +{{- define "appdynamics-otel-collector.appendEnv" -}} +{{- $spec := get .Values "spec" }} +{{- $specEnv := get $spec "env" | deepCopy }} +{{- if not $specEnv }} +{{- $specEnv = list }} +{{- end }} +{{- if.Values.setPodUID }} +{{- $specEnv = append $specEnv (include "appdynamics-otel-collector.downwardEnvVar" (dict "envName" "POD_UID" "path" "metadata.uid") | fromYaml ) }} +{{- end}} +{{- if .Values.clientSecretEnvVar -}} +{{- $specEnv = append $specEnv (include "appdynamics-otel-collector.clientSecretEnvVar" . | fromYaml ) }} +{{- end }} + +{{- $specEnv = append $specEnv (include "appdynamics-otel-collector.downwardEnvVar" (dict "envName" "NODE_NAME" "path" "spec.nodeName") | fromYaml)}} +env: +{{- $specEnv | toYaml | nindent 2}} +{{- end }} + +{{/* + Set serviceAccount.name into spec.serviceAccount in the value file. + If the spec.serviceAccount is already set, the serviceAccount.name won't take any effect. + If neither spec.serviceAccount and serviceAccount.name are set, the default value will be populated to spec.serviceAccount. +*/}} +{{- define "appdynamics-otel-collector.valueServiceAccount" -}} +{{- if not .Values.spec.serviceAccount }} +serviceAccount: {{(.Values.serviceAccount.name | default (include "appdynamics-otel-collector.serviceAccountName" .))}} +{{- end }} +{{- end}} + +{{/* + Calculate the target allocator service account name. + When enable the prometheuse, the prority for finding target allocator service account is (from high to low) + - spec.targetAllocator.name + - targetAllocatorServiceServiceAccount.name + - default value - collector name concat with -target-allocator, e.g. "my-collector-target-allocator" +*/}} +{{- define "appdynamics-otel-collector.valueTargetAllocatorServiceAccount" -}} +{{- if .Values.spec.targetAllocator }} +{{- .Values.spec.targetAllocator.serviceAccount | default .Values.targetAllocatorServiceAccount.name | default (include "appdynamics-otel-collector.targetAllocatorServiceAccountName" .) }} +{{- else }} +{{- .Values.targetAllocatorServiceAccount.name | default (include "appdynamics-otel-collector.targetAllocatorServiceAccountName" .) -}} +{{- end }} +{{- end }} + + +{{- define "appdynamics-otel-collector.serverDefaultPaths" -}} +{{- if .secret }} +{{ $path := .path | default "/etc/otel/certs/receiver"}} +{{- if .secret.secretKeys.caCert}} +ca_file: {{$path}}/{{.secret.secretKeys.caCert}} +{{- if .mtlsEnabled}} +client_ca_file: {{$path}}/{{.secret.secretKeys.caCert}} +{{- end}} +{{- end}} +cert_file: {{$path}}/{{.secret.secretKeys.tlsCert}} +key_file: {{$path}}/{{.secret.secretKeys.tlsKey}} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.clientDefaultPaths" -}} +{{ $path := .path | default "/etc/otel/certs/exporter"}} +{{- if .secretKeys.caCert}} +ca_file: {{$path}}/{{.secretKeys.caCert}} +{{- end }} +cert_file: {{$path}}/{{.secretKeys.tlsCert}} +key_file: {{$path}}/{{.secretKeys.tlsKey}} +{{- end }} + +{{- define "appdynamics-otel-collector.clientSecretVolumePath" -}} +{{- $path := .path | default "/etc/otel/oauth/secret" -}} +${file:{{$path}}/{{.secretKey}}} +{{- end }} + +{{- define "appdynamics-otel-collector.tlsSecrets" -}} +secret: + secretName: {{.secretName}} + items: + {{- if .secretKeys.caCert}} + - key: {{.secretKeys.caCert}} + path: {{.secretKeys.caCert}} + {{- end }} + - key: {{required ".secretKeys.tlsCert is required" .secretKeys.tlsCert}} + path: {{.secretKeys.tlsCert}} + - key: {{required ".secretKeys.tlsKey is required" .secretKeys.tlsKey}} + path: {{.secretKeys.tlsKey}} +{{- end}} + +{{- define "appdynamics-otel-collector.clientSecret" -}} +secret: + secretName: {{.secretName}} + items: + - key: {{.secretKey}} + path: {{.secretKey}} +{{- end }} + +{{/* + calculate volume mounts for tls secret and client secret +*/}} +{{- define "appdynamics-otel-collector.valuesVolume" -}} +{{- if or .Values.clientSecretVolume (or .Values.global.tls.otelReceiver.secret .Values.global.tls.otelExporter.secret)}} +volumeMounts: +{{- with .Values.global.tls.otelReceiver.secret}} +{{ $path := .path | default "/etc/otel/certs/receiver"}} +- name: tlsotelreceiversecrets + mountPath: {{$path}} +{{- end}} +{{- with .Values.global.tls.otelExporter.secret}} +{{ $path := .path | default "/etc/otel/certs/exporter"}} +- name: tlsotelexportersecrets + mountPath: {{$path}} +{{- end}} +{{- with .Values.clientSecretVolume}} +{{ $path := .path | default "/etc/otel/oauth/secret"}} +- name: clientsecret + mountPath: {{$path}} +{{- end }} + +volumes: +{{- with .Values.global.tls.otelReceiver.secret}} +- name: tlsotelreceiversecrets +{{- (include "appdynamics-otel-collector.tlsSecrets" .) | nindent 2}} +{{- end }} +{{- with .Values.global.tls.otelExporter.secret}} +- name: tlsotelexportersecrets +{{- (include "appdynamics-otel-collector.tlsSecrets" .) | nindent 2}} +{{- end }} +{{- with .Values.clientSecretVolume}} +- name: clientsecret +{{- (include "appdynamics-otel-collector.clientSecret" .) | nindent 2}} +{{- end }} + +{{- end }} +{{- end }} + +{{/* + Generate tls cert paths from volume mounts dervied from secrets +*/}} +{{- define "appdynamics-otel-collector.tlsConfigFromSecrets" -}} +{{- with .Values.global.tls.otelReceiver}} +receivers: + otlp: + protocols: + grpc: + tls: +{{- (include "appdynamics-otel-collector.serverDefaultPaths" .) | nindent 10}} + http: + tls: +{{- (include "appdynamics-otel-collector.serverDefaultPaths" .) | nindent 10}} + otlp/lca: + protocols: + grpc: + tls: +{{- (include "appdynamics-otel-collector.serverDefaultPaths" .) | nindent 10}} + http: + tls: +{{- (include "appdynamics-otel-collector.serverDefaultPaths" .) | nindent 10}} +{{- end }} +{{- with .Values.global.tls.otelExporter.secret }} +extensions: + oauth2client: + tls: +{{- (include "appdynamics-otel-collector.clientDefaultPaths" .) | nindent 6}} +exporters: + otlphttp: + tls: +{{- (include "appdynamics-otel-collector.clientDefaultPaths" .) | nindent 6}} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.truncated" -}} +processors: + transform/truncate: + error_mode: ignore + trace_statements: + {{- if .Values.presets.truncated.trace.span }} + - context: span + statements: + - truncate_all(attributes, {{.Values.presets.truncated.trace.span}}) + {{- end }} + {{- if .Values.presets.truncated.trace.spanevent }} + - context: spanevent + statements: + - truncate_all(attributes, {{.Values.presets.truncated.trace.spanevent}}) + {{- end }} + {{- if .Values.presets.truncated.trace.resource }} + - context: resource + statements: + - truncate_all(attributes, {{.Values.presets.truncated.trace.resource}}) + {{- end }} + {{- if .Values.presets.truncated.trace.scope }} + - context: scope + statements: + - truncate_all(attributes, {{.Values.presets.truncated.trace.scope}}) + {{- end }} + metric_statements: + {{- if .Values.presets.truncated.metric.resource }} + - context: resource + statements: + - truncate_all(attributes, {{.Values.presets.truncated.metric.resource}}) + {{- end }} + {{- if .Values.presets.truncated.metric.scope }} + - context: scope + statements: + - truncate_all(attributes, {{.Values.presets.truncated.metric.scope}}) + {{- end }} + {{- if .Values.presets.truncated.metric.datapoint }} + - context: datapoint + statements: + - truncate_all(attributes, {{.Values.presets.truncated.metric.datapoint}}) + {{- end }} + log_statements: + {{- if .Values.presets.truncated.log.resource }} + - context: resource + statements: + - truncate_all(attributes, {{.Values.presets.truncated.log.resource}}) + {{- end }} + {{- if .Values.presets.truncated.log.scope }} + - context: scope + statements: + - truncate_all(attributes, {{.Values.presets.truncated.log.scope}}) + {{- end }} + {{- if .Values.presets.truncated.log.log }} + - context: log + statements: + - truncate_all(attributes, {{.Values.presets.truncated.log.log}}) + {{- end }} +{{- end }} + +{{/* + Auto generated otel collector configs. We need to compute memoryLimiter config from spec, thus we defined to template variable + var1 - global scope + var2 - computed spec +*/}} +{{- define "appdynamics-otel-collector.autoValueConfig" -}} +{{- $otelConfig := tpl (get .var1.Values "config" | deepCopy | toYaml) .var1 | fromYaml}} +{{- $mergedConfig := mustMergeOverwrite $otelConfig (include "appdynamics-otel-collector.derivedConfig" .var1 | fromYaml )}} +{{- if eq .var1.Values.presets.presampler.deploy_mode "gateway"}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.presampler" .var1 | fromYaml )}} +{{- end }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.samplerdebug" .var1 | fromYaml )}} + +{{- $deploy_mode := split "_" .var1.Values.presets.tailsampler.deploy_mode }} +{{- if and .var1.Values.presets.tailsampler.enable (eq $deploy_mode._0 "gateway")}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.loadbalancing" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.tlsConfig.loadbalancing" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.tlsConfigFromSecrets.loadbalancing" .var1 | fromYaml )}} +{{- end }} + +{{- if and .var1.Values.presets.tailsampler.enable (eq $deploy_mode._1 "gateway")}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.sampler" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.tlsConfig.tracegrouping" .var1 | fromYaml )}} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tailsampler.tlsConfigFromSecrets.tracegrouping" .var1 | fromYaml )}} +{{- end }} + +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tlsConfigFromSecrets" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.tlsConfig" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.memoryLimiter" .var2.resources.limits | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.truncated" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.selfTelemetry" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagement" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.agentManagementSelfTelemetry" .var1 | fromYaml ) }} +{{- if .var1.Values.enableNetworkMonitoring }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.networkMonitoring" .var1 | fromYaml ) }} +{{- end }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.traceContextPropagation" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.chartInfo" .var1 | fromYaml ) }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (include "appdynamics-otel-collector.nonAppDTransformConfig" .var1 | fromYaml ) }} +{{- $mergedConfig := tpl ($mergedConfig | toYaml) .var1 | fromYaml }} +{{- if .var1.Values.configOverride }} +{{- $mergedConfig := mustMergeOverwrite $mergedConfig (deepCopy .var1.Values.configOverride)}} +{{- end }} +{{- toYaml $mergedConfig }} +{{- end }} + + +{{/* + convert config map to yaml multiline string +*/}} +{{- define "appdynamics-otel-collector.configToYamlString" -}} +config: |- +{{- . | toYaml | nindent 2 }} +{{- end }} + +{{- define "appdynamics-otel-collector.selfTelemetry.spec" -}} +#{{- if .Values.selfTelemetry }} +#args: +# "feature-gates": "telemetry.useOtelForInternalMetrics,telemetry.useOtelWithSDKConfigurationForInternalTelemetry" +{{- end }} +{{- end }} + +{{/* + Basic spec. Combine the sections into spec. +*/}} +{{- define "appdynamics-otel-collector.spec" -}} +{{- $spec := .Values.spec | deepCopy }} +{{- $spec := include "appdynamics-otel-collector.appendEnv" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := include "appdynamics-otel-collector.valuesVolume" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := include "appdynamics-otel-collector.valueServiceAccount" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $spec := include "appdynamics-otel-collector.selfTelemetry.spec" . | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- $config := include "appdynamics-otel-collector.autoValueConfig" (dict "var1" . "var2" $spec) | deepCopy | fromYaml }} +{{- $spec := include "appdynamics-otel-collector.configToYamlString" $config | fromYaml | deepCopy | mustMergeOverwrite $spec }} +{{- toYaml $spec }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-daemonset.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-daemonset.yaml new file mode 100644 index 00000000..516c56b8 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-daemonset.yaml @@ -0,0 +1,43 @@ +{{- if .Values.install -}} +{{- if or .Values.enableFileLog (not .Values.enablePrometheus) }} + +{{- if (has "linux" .Values.os) }} +apiVersion: opentelemetry.io/v1alpha1 +kind: OpenTelemetryCollector +metadata: + annotations: +{{- .Values.annotations | toYaml | nindent 4 }} + labels: +{{- include "appdynamics-otel-collector.finalLabelsDaemonset" . | nindent 4 }} + name: {{ include "appdynamics-otel-collector.daemonset.fullname" .}} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: +{{- include "appdynamics-otel-collector-daemonset-linux.spec" . | nindent 2 }} +{{- if .Values.status }} +status: +{{- .Values.status | toYaml | nindent 2 }} +{{- end }} +{{- end }} + +--- + +{{- if (has "windows" .Values.os) }} +apiVersion: opentelemetry.io/v1alpha1 +kind: OpenTelemetryCollector +metadata: + annotations: +{{- .Values.annotations | toYaml | nindent 4 }} + labels: +{{- include "appdynamics-otel-collector.finalLabelsDaemonset" . | nindent 4 }} + name: {{ include "appdynamics-otel-collector.daemonset.windows.fullname" .}} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: +{{- include "appdynamics-otel-collector-daemonset-windows.spec" . | nindent 2 }} +{{- if .Values.status }} +status: +{{- .Values.status | toYaml | nindent 2 }} +{{- end }} +{{- end }} + +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-sidecar.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-sidecar.yaml new file mode 100644 index 00000000..0e0155c2 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-sidecar.yaml @@ -0,0 +1,35 @@ +{{- if .Values.install -}} +{{- if or (and .Values.presets.tailsampler.enable (contains "sidecar" .Values.presets.tailsampler.deploy_mode)) (or .Values.presets.multi_tier.sidecar.enable .Values.presets.multi_tier.sidecar.client_side_loadbalancing) }} + +{{- if (has "linux" .Values.os) }} +apiVersion: opentelemetry.io/v1alpha1 +kind: OpenTelemetryCollector +metadata: + name: {{ include "appdynamics-otel-collector.sidecar.fullname" .}} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: +{{- include "appdynamics-otel-collector.sidecar.linux.spec" . | nindent 2 }} +{{- if .Values.status }} +status: +{{- .Values.status | toYaml | nindent 2 }} +{{- end }} +{{- end }} + +--- + +{{- if (has "windows" .Values.os) }} +apiVersion: opentelemetry.io/v1alpha1 +kind: OpenTelemetryCollector +metadata: + name: {{ include "appdynamics-otel-collector.sidecar.windows.fullname" .}} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: +{{- include "appdynamics-otel-collector.sidecar.windows.spec" . | nindent 2 }} +{{- if .Values.status }} +status: +{{- .Values.status | toYaml | nindent 2 }} +{{- end }} +{{- end }} + +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-statefulset.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-statefulset.yaml new file mode 100644 index 00000000..ece492db --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-statefulset.yaml @@ -0,0 +1,43 @@ +{{- if .Values.install -}} +{{- if .Values.enablePrometheus }} + +{{- if (has "linux" .Values.os) }} +apiVersion: opentelemetry.io/v1alpha1 +kind: OpenTelemetryCollector +metadata: + annotations: +{{- .Values.annotations | toYaml | nindent 4 }} + labels: +{{- include "appdynamics-otel-collector.finalLabelsStatefulset" . | nindent 4 }} + name: {{ include "appdynamics-otel-collector.statefulset.fullname" .}} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: +{{- include "appdynamics-otel-collector-statefulset-linux.spec" . | nindent 2 }} +{{- if .Values.status }} +status: +{{- .Values.status | toYaml | nindent 2 }} +{{- end }} +{{- end }} + +--- + +{{- if (has "windows" .Values.os) }} +apiVersion: opentelemetry.io/v1alpha1 +kind: OpenTelemetryCollector +metadata: + annotations: +{{- .Values.annotations | toYaml | nindent 4 }} + labels: +{{- include "appdynamics-otel-collector.finalLabelsStatefulset" . | nindent 4 }} + name: {{ include "appdynamics-otel-collector.statefulset.windows.fullname" .}} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: +{{- include "appdynamics-otel-collector-statefulset-windows.spec" . | nindent 2 }} +{{- if .Values.status }} +status: +{{- .Values.status | toYaml | nindent 2 }} +{{- end }} +{{- end }} + +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-tailsampler.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-tailsampler.yaml new file mode 100644 index 00000000..1ccad6db --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-tailsampler.yaml @@ -0,0 +1,43 @@ +{{- if .Values.install -}} +{{- if and .Values.presets.tailsampler.enable (contains "sampler" .Values.presets.tailsampler.deploy_mode) }} + +{{- if (has "linux" .Values.presets.multi_tier.tailsampler.os) }} +apiVersion: opentelemetry.io/v1alpha1 +kind: OpenTelemetryCollector +metadata: + annotations: +{{- .Values.annotations | toYaml | nindent 4 }} + labels: +{{- include "appdynamics-otel-collector.tailsampler.finalLabels" . | nindent 4 }} + name: {{ include "appdynamics-otel-collector.tailsampler.fullname" .}} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: +{{- include "appdynamics-otel-collector.tailsampler.linux.spec" . | nindent 2 }} +{{- if .Values.status }} +status: +{{- .Values.status | toYaml | nindent 2 }} +{{- end }} +{{- end }} + +--- + +{{- if (has "windows" .Values.presets.multi_tier.tailsampler.os) }} +apiVersion: opentelemetry.io/v1alpha1 +kind: OpenTelemetryCollector +metadata: + annotations: +{{- .Values.annotations | toYaml | nindent 4 }} + labels: +{{- include "appdynamics-otel-collector.tailsampler.finalLabels" . | nindent 4 }} + name: {{ include "appdynamics-otel-collector.tailsampler.windows.fullname" .}} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: +{{- include "appdynamics-otel-collector.tailsampler.windows.spec" . | nindent 2 }} +{{- if .Values.status }} +status: +{{- .Values.status | toYaml | nindent 2 }} +{{- end }} +{{- end }} + +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/rbac.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/rbac.yaml new file mode 100644 index 00000000..1c63e347 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/rbac.yaml @@ -0,0 +1,33 @@ +{{ if and .Values.rbac.create .Values.install }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "appdynamics-otel-collector.fullname" . }}-clusterrole + labels: + {{- include "appdynamics-otel-collector.labels" . | nindent 4 }} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +{{- with .Values.rbac.rules }} +rules: + {{- toYaml . | nindent 2 }} +{{- end }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "appdynamics-otel-collector.fullname" . }}-clusterrolebinding + namespace: {{ include "appdynamics-otel-collector.namespace" .}} + labels: + {{- include "appdynamics-otel-collector.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "appdynamics-otel-collector.fullname" . }}-clusterrole +subjects: + - kind: ServiceAccount + {{- with $spec := include "appdynamics-otel-collector.valueServiceAccount" . | fromYaml }} + name: {{ index $spec "serviceAccount" }} + {{- end}} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} + +{{ end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/service-account.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/service-account.yaml new file mode 100644 index 00000000..561610d7 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/service-account.yaml @@ -0,0 +1,19 @@ +{{ if .Values.install -}} +{{- if and .Values.serviceAccount .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "appdynamics-otel-collector.serviceAccountName" . }} + labels: + {{- include "appdynamics-otel-collector.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +{{- with .Values.serviceAccount.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/service.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/service.yaml new file mode 100644 index 00000000..32f3d545 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/service.yaml @@ -0,0 +1,129 @@ +{{- if .Values.install -}} +{{/*Global Servce*/}} +apiVersion: v1 +kind: Service +metadata: + labels: +{{- include "appdynamics-otel-collector.labels" . | nindent 4 }} + name: {{ .Values.service.name }} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: + selector: + app.kubernetes.io/component: opentelemetry-collector +{{- include "appdynamics-otel-collector.gateway.selectorLabels" . | nindent 4 }} + type: {{ .Values.service.type }} + ports: +{{- .Values.service.ports | toYaml | nindent 2}} +{{- if .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} +{{- end }} + +--- + +{{/*Global Servce - headless */}} +{{- if .Values.presets.multi_tier.sidecar.client_side_loadbalancing }} +apiVersion: v1 +kind: Service +metadata: + labels: +{{- include "appdynamics-otel-collector.labels" . | nindent 4 }} + name: {{ .Values.service.name -}}-headless + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: + selector: + app.kubernetes.io/component: opentelemetry-collector +{{- include "appdynamics-otel-collector.gateway.selectorLabels" . | nindent 4 }} + type: {{ .Values.service.type }} +{{- include "appdynamics-otel-collector.valueServicePorts" . | indent 2 }} + clusterIP: None +{{- end }} + +--- + +{{/*Sampler Service*/}} +{{- if .Values.presets.tailsampler.enable }} +apiVersion: v1 +kind: Service +metadata: + labels: +{{- include "appdynamics-otel-collector.labels" . | nindent 4 }} + name: {{ .Values.presets.tailsampler.service.name }} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: + selector: + app.kubernetes.io/component: opentelemetry-collector +{{- include "appdynamics-otel-collector.tailsampler.selectorLabels" . | nindent 4 }} + type: {{ .Values.presets.tailsampler.service.type }} + ports: +{{- .Values.presets.tailsampler.service.ports | toYaml | nindent 2}} +{{- if .Values.presets.tailsampler.service.clusterIP }} + clusterIP: {{ .Values.presets.tailsampler.service.clusterIP }} +{{- end }} +{{- end }} + +--- + +{{/*Daemonset Servce*/}} +{{/*Only enabled when both deployments are required*/}} +{{- if and .Values.enablePrometheus .Values.enableFileLog -}} +apiVersion: v1 +kind: Service +metadata: + labels: +{{- include "appdynamics-otel-collector.labels" . | nindent 4 }} + name: {{ .Values.service.name }}-ds + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: + selector: + app.kubernetes.io/component: opentelemetry-collector +{{- include "appdynamics-otel-collector.selectorLabelsDaemonset" . | nindent 4 }} + type: {{ .Values.service.type }} + ports: +{{- .Values.service.ports | toYaml | nindent 2}} +{{- if .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} +{{- end }} +{{- end }} + +--- + +{{/*Statefulset Servce*/}} +{{/*Only enabled when both deployments are required*/}} +{{- if and .Values.enablePrometheus .Values.enableFileLog -}} +apiVersion: v1 +kind: Service +metadata: + labels: +{{- include "appdynamics-otel-collector.labels" . | nindent 4 }} + name: {{ .Values.service.name }}-ss + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +spec: + selector: + app.kubernetes.io/component: opentelemetry-collector +{{- include "appdynamics-otel-collector.selectorLabelsStatefulset" . | nindent 4 }} + type: {{ .Values.service.type }} + ports: +{{- .Values.service.ports | toYaml | nindent 2}} +{{- if .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} +{{- end }} +{{- end }} + +--- + +{{/*Custom Servce*/}} +{{/*Used for create services that the name is configurable*/}} +{{- if ((.Values.global.customService).enable | default .Values.customService.enable) -}} +apiVersion: v1 +kind: Service +metadata: + labels: +{{- include "appdynamics-otel-collector.labels" . | nindent 4 }} + name: {{ (.Values.global.customService).name | default .Values.customService.name | required "customService.name must be non empty when enabled" }} + namespace: {{ (.Values.global.customService).namespace | default .Values.customService.namespace }} +spec: + type: ExternalName + externalName: {{.Values.service.name}}.{{ include "appdynamics-otel-collector.namespace" .}}.svc.cluster.local +{{- end }} + +{{- end}} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/target-allocator-rbac.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/target-allocator-rbac.yaml new file mode 100644 index 00000000..badddc60 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/target-allocator-rbac.yaml @@ -0,0 +1,39 @@ +{{ if .Values.install -}} +{{- if and .Values.enablePrometheus (and .Values.targetAllocatorServiceAccount .Values.targetAllocatorServiceAccount.create) }} + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: appd-otel-collector-target-allocator-role + namespace: {{ include "appdynamics-otel-collector.namespace" . }} +rules: +- apiGroups: + - '' + resources: + - 'pods' + - 'nodes' + - 'endpoints' + - 'services' + verbs: + - 'get' + - 'list' + - 'watch' + + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: appd-otel-collector-target-allocator-rolebinding + namespace: {{ include "appdynamics-otel-collector.namespace" .}} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: appd-otel-collector-target-allocator-role +subjects: + - kind: ServiceAccount + name: {{ include "appdynamics-otel-collector.valueTargetAllocatorServiceAccount" . }} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} + +{{ end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/target-allocator-service-account.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/target-allocator-service-account.yaml new file mode 100644 index 00000000..14b6fde6 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/target-allocator-service-account.yaml @@ -0,0 +1,17 @@ +{{ if .Values.install -}} +{{- if and .Values.enablePrometheus (and .Values.targetAllocatorServiceAccount .Values.targetAllocatorServiceAccount.create) -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "appdynamics-otel-collector.valueTargetAllocatorServiceAccount" . }} + namespace: {{ include "appdynamics-otel-collector.namespace" .}} + {{- with .Values.targetAllocatorServiceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.targetAllocatorServiceAccount.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/tests/simple-test-loadgen.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/tests/simple-test-loadgen.yaml new file mode 100644 index 00000000..055e9d15 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/tests/simple-test-loadgen.yaml @@ -0,0 +1,20 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: loadgen + annotations: + "helm.sh/hook": test +spec: + template: + spec: + nodeSelector: + kubernetes.io/os: "linux" + containers: + - name: loadgen-grpc + image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/tracegen:latest + command: ["/tracegen", "-otlp-endpoint=appdynamics-otel-collector-service:4317", "-otlp-insecure=true"] + - name: loadgen-http + image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/tracegen:latest + command: ["/tracegen", "-otlp-endpoint=appdynamics-otel-collector-service:4318", "-otlp-insecure=true", "-otlp-http=true"] + restartPolicy: Never + backoffLimit: 4 \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/values.schema.json b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/values.schema.json new file mode 100644 index 00000000..f19d58c1 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/values.schema.json @@ -0,0 +1,696 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "title": "Values", + "additionalProperties": false, + "properties": { + "global": { + "type": "object", + "properties": { + "clusterName": { + "description": "The name for cluster where the collectors and target allocator are deployed, required when enablePrometheus set to true", + "type": "string" + }, + "clusterId": { + "description": "The uid of kube-system namespace, required when helm lookup is not supported and enablePrometheus/selfTelemetry is set to true", + "type": "string" + }, + "customService": { + "description": "A custom service which its name and namespace can be configured for user application. Shared with instrumentation chart, override .customerService.", + "type": "object", + "additionalProperties": false, + "properties": { + "enable" : { + "description": "Whether the custom service will be created, false by default", + "type": "boolean" + }, + "name": { + "description": "The name for the custom service", + "type": "string" + }, + "namespace": { + "description": "The namespace for the custom service", + "type": "string" + } + } + } + } + }, + "install": { + "description": "Install flag for Otel, 'true' will install/upgrade it, 'false' will not install/uninstall it", + "type": "boolean" + }, + "nameOverride": { + "description": "Override name of the chart used in Kubernetes object names.", + "type": "string" + }, + "fullnameOverride": { + "description": "Override fully qualified app name.", + "type": "string" + }, + "clientId": { + "description": "AppDynamics oauth2 client id", + "type": "string" + }, + "clientSecret": { + "description": "AppDynamics oauth2 client secret plain text.", + "type": ["string"] + }, + "clientSecretEnvVar": { + "description": "AppDynamics oauth2 client secret environment variable.", + "type": ["object"] + }, + "clientSecretVolume": { + "description": "AppDynamics oauth2 client secret volume.", + "type": ["object"] + }, + "tenantId": { + "description": "Tenant id, if not provided, the chart will try to extract the tenantId from tokenUrl.", + "type": ["string"] + }, + "tokenUrl": { + "description": "AppDynamics oauth2 token refreshurl", + "type": "string" + }, + "endpoint": { + "description": "AppDynamics otlp endpoint url", + "type": "string" + }, + "spec": { + "type": "object", + "description": "The spec section of OpenTelemetry Operator. Refer to https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec for possible properties" + }, + "traceContextPropagation": { + "type": "boolean", + "description": "to enable/disbale traceparent header propagation for export requests made by collector." + }, + "status": { + "type": "object", + "description": "The status section of OpenTelemetry Operator. Refer to https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorstatus for possible properties" + }, + "config": { + "description": "OpenTelemetry Collector Configuration. It is the recommended way to set the collector config. If spec.config is set, this property won't take effect. Refer to the OpenTelemetry Collector documentation for details.", + "type": "object" + }, + "configOverride": { + "description": "Any additional OpenTelemetry Collector Configuration for the enabled configuration. We can also use this field to remove/add new components to the pipelines", + "type": "object" + }, + "sendChartInfo": { + "description": "sendChartInfo when set to true, will add the chart name and version to the http headers for sending to AppDynamics Cloud for debugging purpose. It is false by default", + "type": "boolean" + }, + "serviceAccount": { + "description": "ServiceAccount applied by this chart, disable it by setting create to false.", + "type": "object", + "additionalProperties": false, + "properties": { + "create": { + "type": "boolean" + }, + "annotations": { + "type": "object" + }, + "name": { + "type": "string" + }, + "imagePullSecrets": { + "type": "array" + } + }, + "required": [ + "create" + ] + }, + "service": { + "description": "service expose collector for external traffics.", + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "ClusterIP", + "NodePort", + "LoadBalancer", + "ExternalName" + ] + }, + "ports": { + "type": "array" + }, + "clusterIP": { + "type": "string" + } + } + }, + "rbac": { + "description": "RBAC rules associated with the service account. If created, a Role will be created and bind with the collector service account", + "type": "object", + "additionalProperties": false, + "properties": { + "rules": { + "type": "array" + }, + "create": { + "type": "boolean" + } + }, + "required": [ + "create" + ] + }, + "selfTelemetry": { + "description": "Open telemetry collector metrics", + "type": "boolean" + }, + "selfTelemetryServiceName": { + "description": "Open telemetry collector service name", + "type": "string" + }, + "selfTelemetryServiceNamespace": { + "description": "Open telemetry collector service namespace", + "type": "string" + }, + "enablePrometheus": { + "description": "Enable the prometheus related deployment, it will deploy a target allocator and change collector replica mode to be statfulset.", + "type": "boolean" + }, + "setPodUID":{ + "description": "setPodUID when set to true will set pod uid to the collector self-telemetry resrouce.", + "type": "boolean" + }, + "targetAllocatorServiceAccount": { + "description": "ServiceAccount for target allocator, only enable when enablePrometheus equals true, disable it by setting create to false.", + "type": "object", + "additionalProperties": false, + "properties": { + "create": { + "type": "boolean" + }, + "annotations": { + "type": "object" + }, + "name": { + "type": "string" + }, + "imagePullSecrets": { + "type": "array" + } + }, + "required": [ + "create" + ] + }, + "os": { + "description": "Choose the os type for otel collector to run, useful when the cluster has mixed os types.", + "type": "array" + }, + "env":{ + "description": "os specific otel collector spec.", + "type": "object", + "additionalProperties": false, + "properties": { + "linux": { + "type": "object", + "description": "The spec and configuration override objects for Linux deployments of the Cisco AppDynamics Distribution of OpenTelemetry Collector. It will overrides the configs from mode.statefulset and mode.daemonset", + "additionalProperties": false, + "properties": { + "spec": { + "type": "object", + "description": "The desired state of the Cisco AppDynamics Distribution of OpenTelemetry Collector. For the full list of settings, see https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec" + }, + "configOverride": { + "type": "object", + "description": "The configurations for the Cisco AppDynamics Distribution of OpenTelemetry Collector. This environment variable will override the default configurations provided by the Helm chart values. For detailed configurations, see https://opentelemetry.io/docs/collector/configuration/." + }, + "mode": { + "type": "object", + "description": "The spec and configuration override objects for the Linux deployment modes of the Cisco AppDynamics Distribution of OpenTelemetry Collector.", + "properties": { + "daemonset": { + "type": "object", + "additionalProperties": false, + "properties": { + "spec": { + "type": "object", + "description": "The desired state of the Cisco AppDynamics Distribution of OpenTelemetry Collector. For the full list of settings, see https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec" + }, + "configOverride": { + "type": "object", + "description": "The configurations for the Cisco AppDynamics Distribution of OpenTelemetry Collector. This environment variable will override the default configurations provided by the Helm chart values. For detailed configurations, see https://opentelemetry.io/docs/collector/configuration/." + } + } + }, + "statefulset": { + "type": "object", + "additionalProperties": false, + "properties": { + "spec": { + "type": "object", + "description": "The desired state of the Cisco AppDynamics Distribution of OpenTelemetry Collector. For the full list of settings, see https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec" + }, + "configOverride": { + "type": "object", + "description": "The configurations for the Cisco AppDynamics Distribution of OpenTelemetry Collector. This environment variable will override the default configurations provided by the Helm chart values. For detailed configurations, see https://opentelemetry.io/docs/collector/configuration/." + } + } + } + } + } + } + }, + "windows": { + "type": "object", + "description": "The spec and configuration override objects for Windows deployments of the Cisco AppDynamics Distribution of OpenTelemetry Collector. It will overrides the configs from mode.statefulset and mode.daemonset", + "additionalProperties": false, + "properties": { + "spec": { + "type": "object", + "description": "The desired state of the Cisco AppDynamics Distribution of OpenTelemetry Collector. For the full list of settings, see https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec" + }, + "configOverride": { + "type": "object", + "description": "The configurations for the Cisco AppDynamics Distribution of OpenTelemetry Collector. This environment variable will override the default configurations provided by the Helm chart values. For detailed configurations, see https://opentelemetry.io/docs/collector/configuration/." + }, + "mode": { + "type": "object", + "description": "The spec and configuration override objects for the Windows deployment modes of the Cisco AppDynamics Distribution of OpenTelemetry Collector.", + "properties": { + "daemonset": { + "type": "object", + "additionalProperties": false, + "properties": { + "spec": { + "type": "object", + "description": "The desired state of the Cisco AppDynamics Distribution of OpenTelemetry Collector. For the full list of settings, see https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec" + }, + "configOverride": { + "type": "object", + "description": "The configurations for the Cisco AppDynamics Distribution of OpenTelemetry Collector. This environment variable will override the default configurations provided by the Helm chart values. For detailed configurations, see https://opentelemetry.io/docs/collector/configuration/." + } + } + }, + "statefulset": { + "type": "object", + "additionalProperties": false, + "properties": { + "spec": { + "type": "object", + "description": "The desired state of the Cisco AppDynamics Distribution of OpenTelemetry Collector. For the full list of settings, see https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec" + }, + "configOverride": { + "type": "object", + "description": "The configurations for the Cisco AppDynamics Distribution of OpenTelemetry Collector. This environment variable will override the default configurations provided by the Helm chart values. For detailed configurations, see https://opentelemetry.io/docs/collector/configuration/." + } + } + } + } + } + } + } + } + }, + "annotations":{ + "description": "user provided annotations.", + "type": "object" + }, + "labels":{ + "description": "user provided labels.", + "type": "object" + }, + "mode":{ + "description": "spec and config override for different deployment modes", + "type": "object", + "additionalProperties": false, + "properties": { + "daemonset": { + "type": "object", + "description": "The spec and configuration override objects for DaemonSet deployments of the Cisco AppDynamics Distribution of OpenTelemetry Collector.", + "properties": { + "spec": { + "type": "object", + "description": "The desired state of the Cisco AppDynamics Distribution of OpenTelemetry Collector. For the full list of settings, see https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec" + }, + "configOverride": { + "type": "object", + "description": "The configurations for the Cisco AppDynamics Distribution of OpenTelemetry Collector. This environment variable will override the default configurations provided by the Helm chart values. For detailed configurations, see https://opentelemetry.io/docs/collector/configuration/." + } + } + }, + "statefulset": { + "type": "object", + "description": "the spec and configuration override objects for StatefulSet deployments of the Cisco AppDynamics Distribution of OpenTelemetry Collector.", + "properties": { + "spec": { + "type": "object", + "description": "The desired state of the Cisco AppDynamics Distribution of OpenTelemetry Collector. For the full list of settings, see https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec" + }, + "configOverride": { + "type": "object", + "description": "The configurations for the Cisco AppDynamics Distribution of OpenTelemetry Collector. This environment variable will override the default configurations provided by the Helm chart values. For detailed configurations, see https://opentelemetry.io/docs/collector/configuration/." + } + } + } + } + }, + "enableFileLog":{ + "description": "enable filelog receiver deployment.", + "type": "boolean" + }, + "filelogReceiverConfig":{ + "description": "filelogReceiverConfig specify configs for filelog receiver.", + "type": "object", + "additionalProperties": false, + "properties": { + "includeLogsPath": { + "type": "array" + }, + "excludeLogsPath": { + "type": "array" + }, + "messageParserPattern": { + "type": "string" + }, + "messageParserType": { + "type": "string" + } + } + }, + "presets":{ + "description": "presets specify a list of pre-configured fuctions.", + "type": "object", + "additionalProperties": false, + "properties": { + "truncated": { + "description": "truncated specify max attributes value length.", + "type": "object", + "truncated": { + "description": "configurations to truncate attributes for OpenTelemetry signals.", + "type": "object", + "additionalProperties": false, + "properties": { + "trace": { + "description": "configurations to truncate attributes for trace signal.", + "type": "object", + "additionalProperties": false, + "properties": { + "resource": { + "description": "max length for trace resouce attribute", + "type": "integer" + }, + "scope": { + "description": "max length for trace scope attribute", + "type": "integer" + }, + "span": { + "description": "max length for span attribute", + "type": "integer" + }, + "spanevent": { + "type": "integer" + } + } + }, + "metric": { + "type": "object", + "additionalProperties": false, + "properties": { + "resource": { + "description": "max length for metric resouce attribute", + "type": "integer" + }, + "scope": { + "description": "max length for trace scope attribute", + "type": "integer" + }, + "datapoint": { + "description": "max length for metric datapoint attribute", + "type": "integer" + } + } + }, + "log": { + "type": "object", + "additionalProperties": false, + "properties": { + "resource": { + "description": "max length for log resouce attribute", + "type": "integer" + }, + "scope": { + "description": "max length for log scope attribute", + "type": "integer" + }, + "log": { + "description": "max length for log attribute", + "type": "integer" + } + } + } + } + } + }, + "multi_tier": { + "description": "multi-tier configurations for different deployments of AppDynamics Distribution of OpenTelemetry Collector", + "type": "object", + "tailsampler": { + "description": "configurations for tail sampling collector", + "type": "object", + "properties": { + "enable": { + "description": "whether the tail sampling collector should be deployed, default false. Tail sampling collector will be deployed automatically when presets.tailsampler.enable set to true and this config will be ignored.", + "type": "boolean" + }, + "os": { + "description": "The operating system that tail sampling collector should be deployed, [linux] by default. If you also want to deploy tail sampling collector to windows, you could change it to [linux, windows]", + "type": "array" + }, + "env": { + "type": "object", + "additionalProperties": false, + "properties": { + "linux": { + "type": "object", + "additionalProperties": false, + "properties": { + "spec": { + "description": "The spec section of OpenTelemetry Operator. Refer to https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec for possible properties", + "type": "object" + }, + "configOverride": { + "description": "Any additional OpenTelemetry Collector Configuration for the enabled configuration. We can also use this field to remove/add new components to the pipelines", + "type": "object" + } + } + }, + "windows": { + "type": "object", + "additionalProperties": false, + "properties": { + "spec": { + "description": "The spec section of OpenTelemetry Operator. Refer to https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec for possible properties", + "type": "object" + }, + "configOverride": { + "description": "Any additional OpenTelemetry Collector Configuration for the enabled configuration. We can also use this field to remove/add new components to the pipelines", + "type": "object" + } + } + } + } + }, + "spec": { + "description": "The spec section of OpenTelemetry Operator. Refer to https://github.com/open-telemetry/opentelemetry-operator/blob/main/docs/api.md#opentelemetrycollectorspec for possible properties", + "type": "object" + }, + "config": { + "description": "OpenTelemetry Collector Configuration. It is the recommended way to set the collector config. If spec.config is set, this property won't take effect. Refer to the OpenTelemetry Collector documentation for details.", + "type": "object" + }, + "configOverride": { + "description": "Any additional OpenTelemetry Collector Configuration for the enabled configuration. We can also use this field to remove/add new components to the pipelines", + "type": "object" + } + } + } + }, + "presampler": { + "description": "presampler config", + "type": "object" + }, + "samplerDebug": { + "description": "samplerDebug config", + "type": "object" + }, + "tailsampler": { + "description": "Configs for tail sampling", + "type": "object", + "properties": { + "enable": { + "description": "Whether tail sampling should be used, default to false", + "type": "boolean" + }, + "deploy_mode": { + "description": "How tail sampling should be deployed, for now only gateway_sampler is available, which means the default gateway_sampler will receive the trace and forward to tail sampling collector for sampling", + "type": "string" + }, + "replicas": { + "description": "The number of tail sampling collector should be deployed.", + "type": "integer" + }, + "service": { + "description": "The tail sampling collector service configs", + "type": "object", + "properties": { + "name": { + "description": "The name of the tail sampling collector, default to be appdynamics-otel-collector-sampler-service", + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "ClusterIP", + "NodePort", + "LoadBalancer", + "ExternalName" + ] + }, + "ports": { + "type": "array" + } + } + }, + "pipeline": { + "description": "The trace processor pipeline for the tail sampling collector, this is where the user can drop or add a certain sampler", + "type": "array" + }, + "trace_classification_and_sampling": { + "description": "Configs for trace_classification_and_sampling processor.", + "type": "object", + "properties": { + "decision_wait": { + "type": "string" + }, + "policies": { + "type": "array" + }, + "samplers": { + "type": "object", + "properties": { + "export_period": { + "type": "string" + }, + "consistent_reservoir_sampler": { + "type": "object" + } + } + } + } + }, + "consistent_proportional_sampler": { + "description": "Configs for consistent_proportional_sampler processor", + "type": "object", + "properties": { + "export_period": { + "type": "string" + }, + "spans_per_period": { + "type": "integer" + }, + "exponential_smooth": { + "type": "number" + }, + "initial_estimate_rate": { + "type": "integer" + } + } + }, + "intermediate_sampler": { + "description": "Configs for intermediate_sampler processor", + "type": "object", + "properties": { + "export_period": { + "type": "string" + }, + "size_limit": { + "type": "integer" + }, + "size_limit_type": { + "type": "string" + }, + "initial_estimate_rate": { + "type": "integer" + } + } + } + } + }, + "selfTelemetry": { + "description": "self-telemetry config", + "type": "object", + "additionalProperties": false, + "properties": { + "exporters": { + "description": "exporters for self telemetry, default otlphttp: {}. By default self telemetry is sent with other metrics together to AppDynamics, the user may add or replace the exporters here to let the self telemetry be sent to other places. Note when a exporter with empty config need to be added, please use {} as value, for example logging: {} instead of logging: null or just logging: ", + "type": "object" + } + } + } + } + }, + "disableOpamp": { + "description": "disable agent management extension communication. By setting this to true, the user can enable agent management extension without connecting it with the platform, the collector can still report self telemetry by setting agentManagementSelfTelemetry to true", + "type": "boolean" + }, + "agentManagement": { + "description": "Enable agent management extension", + "type": "boolean" + }, + "agentManagementSelfTelemetry": { + "description": "Enable agent management extension based self telemetry, it will report the same set of metrics by enabling selfTelemetry, but it will have different resource attribute and use different solution", + "type": "boolean" + }, + "enableNetworkMonitoring": { + "description": "enable the Network Monitoring related receiver & processors", + "type": "boolean" + }, + "enabled": { + "description": "", + "type": "boolean" + }, + "customService": { + "description": "A custom service which its name and namespace can be configured for user application. Note that the default service name, i.e. appdynamics-otel-collector-service, is used by other AppDynamics collectors and shall not be changed", + "type": "object", + "additionalProperties": false, + "properties": { + "enable" : { + "description": "Whether the custom service will be created, false by default", + "type": "boolean" + }, + "name": { + "description": "The name for the custom service", + "type": "string" + }, + "namespace": { + "description": "The namespace for the custom service", + "type": "string" + } + } + } + }, + "required": [ + "clientId", + "tokenUrl", + "endpoint", + "install" + ], + "anyOf": [ + {"required" : ["clientSecret"]}, + {"required" : ["clientSecretEnvVar"]}, + {"required" : ["clientSecretVolume"]} + ] +} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/values.yaml new file mode 100644 index 00000000..98e7e85b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/values.yaml @@ -0,0 +1,522 @@ +nameOverride: "" +fullnameOverride: "" + +install: true +enabled: true + +# data endpoint +endpoint: "" + +#oauth2client required settings +clientId: "" +clientSecretEnvVar: {} +tokenUrl: "" + +labels: {} + +annotations: + "prometheus.io/scrape": "false" + +global: + clusterName: "" + tls: + otelReceiver: + secret: {} + settings: {} + otelExporter: + secret: {} + settings: {} + +# spec is the spec section for opentelemetry operator. +spec: + image: appdynamics/appdynamics-cloud-otel-collector:24.4.1-1598 + # based on the perf testing + resources: + limits: + cpu: 200m + memory: 1Gi + requests: + cpu: 10m + memory: 256Mi + + +# status is the status section for opentelemtry operator +status: {} + +# config is the Collector configs. Other resources configs are in seperated sections below. +config: + extensions: + health_check: + endpoint: 0.0.0.0:13133 + zpages: + endpoint: 0.0.0.0:55679 + + receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 + otlp/lca: + protocols: + grpc: + endpoint: 0.0.0.0:14317 + http: + endpoint: 0.0.0.0:14318 + + processors: + # https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/batchprocessor/README.md + batch: + send_batch_size: 1000 + timeout: 10s + send_batch_max_size: 1000 + batch/traces: + send_batch_size: 1000 + timeout: 10s + send_batch_max_size: 1000 + batch/metrics: + send_batch_size: 1000 + timeout: 10s + send_batch_max_size: 1000 + batch/logs: + send_batch_size: 1000 + timeout: 10s + send_batch_max_size: 1000 + k8sattributes: + passthrough: false + filter/appd: + logs: + include: + match_type: strict + resource_attributes: + - key: telemetry.sdk.name + value: infra-agent + filter/non_appd: + logs: + exclude: + match_type: strict + resource_attributes: + - key: telemetry.sdk.name + value: infra-agent + filter/jvm: + metrics: + metric: + - 'name == "jvm.gc.duration"' + transform/truncate: + transform/jvmmetric: + metric_statements: + - context: metric + statements: + - extract_count_metric(true) where name == "jvm.gc.duration" + - extract_sum_metric(true) where name == "jvm.gc.duration" + - set(unit, "ms") where name == "jvm.gc.duration_sum" + - set(description, "Time spent in a given JVM garbage collector in milliseconds.") where name == "jvm.gc.duration_sum" + - set(unit, "{collections}") where name == "jvm.gc.duration_count" + - set(description, "The number of collections that have occurred for a given JVM garbage collector.") where name == "jvm.gc.duration_count" + metricstransform/jvmdatapoint: + transforms: + - include: ^jvm\.gc\.(duration_count|duration_sum) + match_type: regexp + action: update + operations: + - action: update_label + label: "jvm.gc.action" + new_label: "action" + - action: update_label + label: "jvm.gc.name" + new_label: "gc" + - include: "jvm.gc.duration_sum" + match_type: strict + action: update + new_name: "runtime.jvm.gc.time" + operations: + - action: experimental_scale_value + experimental_scale: 1000 + - action: toggle_scalar_data_type + - include: "jvm.gc.duration_count" + match_type: strict + action: update + new_name: "runtime.jvm.gc.count" + batchbybytesize: {} + + exporters: + otlphttp: + auth: + authenticator: oauth2client + + logging: + verbosity: detailed + + debug: + verbosity: detailed + + service: + extensions: [health_check, oauth2client] + pipelines: + metrics: + receivers: [otlp] + processors: [memory_limiter, transform/jvmmetric, filter/jvm, metricstransform/jvmdatapoint, transform/truncate, batch/metrics, batchbybytesize] # according to doc, "The memory_limiter processor should be the 1st processor configured in the pipeline (immediately after the receivers)." + exporters: [otlphttp] + traces: + receivers: [otlp] + processors: [memory_limiter, k8sattributes, transform/truncate, batch/traces, batchbybytesize] + exporters: [otlphttp] + logs: + receivers: [otlp] + processors: [memory_limiter, filter/non_appd, k8sattributes/logs, transform/logs, transform/truncate, batch/logs, batchbybytesize] + exporters: [otlphttp] + logs/appd: + receivers: [otlp] + processors: [memory_limiter, filter/appd, batch] + exporters: [otlphttp] + logs/lca: + receivers: [otlp/lca] + processors: [memory_limiter] + exporters: [otlphttp] + +# extra otel collector configuration +configOverride: {} + +# service expose collector for external traffics. +service: + name: "appdynamics-otel-collector-service" + ports: + - name: http + port: 4318 + protocol: TCP + targetPort: 4318 + - name: grpc + port: 4317 + protocol: TCP + targetPort: 4317 + - name: grpc-lca + port: 14317 + protocol: TCP + targetPort: 14317 + - name: grpc-ebpf + port: 24317 + protocol: TCP + targetPort: 24317 + type: ClusterIP + +customService: + enable: false + name: "" + namespace: "" + +# serviceAccount is the serviceAccount associated with the collector, set serviceAccount.create to false if you don't need it +serviceAccount: + annotations: {} + create: true + imagePullSecrets: [] + #name: default to be the full name + +rbac: + create: true + rules: + # k8sattributes prcoessor needed rules. + - apiGroups: [""] + resources: ["pods", "namespaces", "endpoints"] + verbs: ["get", "watch", "list"] + - apiGroups: ["apps"] + resources: ["replicasets"] + verbs: ["get", "watch", "list"] + +# tracecontext propgation +traceContextPropagation: true + +# enablePrometheus enable the prometheus related deployment, it will deploy a target allocator and a statefulset. +enablePrometheus: false +# enablePrometheus enable the filelog, it will deploy a daemonset to collector logs on each host. +enableFileLog: false +# disable agent management Opamp communication +disableOpamp: false +# Enable agent management extension +agentManagement: true +# Collector self telemetry +agentManagementSelfTelemetry: false +# Collector self telemetry, will be deprecated in Jan 2024 +selfTelemetry: false +# enableNetworkMonitoring enables the Network Monitoring related receiver & processors +enableNetworkMonitoring: false + +# targetAllocatorServiceAccount only enabled when enablePrometheus=true, +# It will create a service account with a cluster role that have necessary permissions for the allocator to run. +targetAllocatorServiceAccount: + annotations: {} + create: true + imagePullSecrets: [] + #name: default to be the collector name with "-target-allocator" suffix, e.g. "my-collector-target-allocator" + + +# deployment mode specific spec and config overrides. +mode: + statefulset: + spec: + mode: statefulset + daemonset: + spec: + mode: daemonset + +# OS specific spec and config overrides. +os: [linux] +env: + linux: + spec: + nodeSelector: + kubernetes.io/os: "linux" + # mode: + # statefulset: deployment and OS specific spec/config overrides + windows: + spec: + nodeSelector: + kubernetes.io/os: "windows" + livenessProbe: + initialDelaySeconds: 5 + +presets: + samplerDebug: + enable: false + config: + extensions: + appd_data_router: {} + processors: + tracerecord/received: + appd_router_ext: appd_data_router + tracerecord/sampled: + appd_router_ext: appd_data_router + receivers: + appdeventsreceiver: + appd_router_ext: appd_data_router + service: + extensions: [health_check, oauth2client, appd_data_router] + pipelines: + logs/sampler_debug: + receivers: [appdeventsreceiver] + exporters: [otlphttp] + presampler: + enable: false + deploy_mode: gateway # sidecar + pipeline: [memory_limiter, consistent_proportional_sampler/presampler, k8sattributes, batch/traces] + pipeline_sidecar: [memory_limiter, consistent_proportional_sampler/presampler, batch/traces] + #pipeline: [memory_limiter, k8sattributes, consistent_sampler/presampler, batch/traces] replace with this pipeline when testing adding configured p value directly. + consistent_proportional_sampler: + export_period: 1s # the export period for specifying the expected output rate, it is for rate calculation only, NOT for batch interval. The batch interval can be configured at trace_classification_and_sampling.samplers.export_period, or you can add a batch processor before this. + spans_per_period: 1000 # number of spans per request, the expected rate limit is calculated by dividing this number by export_period. The spans per packet is limited by the max packet size, assuming 1MB limit, and each span with size of 1KB + exponential_smooth: 0.1 # start with small number + initial_estimate_rate: 1000 # number of incomming span rate, just give a reasonable guess. + rate_estimator: batch_rate_estimator + sample_mode: presampling + consistent_sampler: + p_value: 1 # user can configure a p value to add to the trace state directly, it is mainly for testing purpose + + # default configuration resulted in about 48% of tier 1 limit, which is 480 request/minute with 1000 spans/request + tailsampler: + enable: false + deploy_mode: gateway_sampler # gateway_sampler, sidecar_gateway, sidecar_sampler, specify the loadbalancer and tailsampling position with _ + replicas: 1 + service: + name: "appdynamics-otel-collector-sampler-service" + type: ClusterIP + clusterIP: None + ports: + - name: sampler + port: 24317 + protocol: TCP + targetPort: 24317 + # groupbyattrs/compact is for compressing the traces with the same resource or scope + pipeline: [memory_limiter, batch/input, intermediate_sampler, trace_classification_and_sampling, consistent_proportional_sampler, groupbyattrs/compact, batch/traces, batchbybytesize] # the sampler pipeline set up + # when deployed as sidecar_sampler, sidecar will export trace to tail sampler directly, thus we need k8sattributes + pipeline_sidecar_loadbalancer: [memory_limiter, k8sattributes, groupbytrace, trace_classification_and_sampling, consistent_proportional_sampler, groupbyattrs/compact, batchbybytesize] + # classification and balanced sampling + groupbytrace: + wait_duration: 30s + trace_classification_and_sampling: + decision_wait: 30s + num_traces: 1000000 # Limit number of traces to keep in memory waiting for decision. + # classification, example considers error, high latency and all other traces, each category will be rate limit separately. + no_wait: true + independent_grouping: true + policies: + - name: errors-policy + type: status_code + sampler_name: "consistent_reservoir_sampler/error" + status_code: + status_codes: [ERROR] + - name: high-latency + type: latency + sampler_name: "consistent_reservoir_sampler/latency" + latency: + threshold_ms: 10000 + - name: always-on + type: always_sample + sampler_name: "consistent_reservoir_sampler/anyother" + # balanced sampler controls the max rate for a category, the proportion among categories is more important because the final export rate is controlled by the following proportional sampler. + samplers: + export_period: 1s + consistent_reservoir_sampler: + error: + reservoir_size: 1000 + latency: + reservoir_size: 1000 + anyother: + reservoir_size: 1000 + # consistent_proportional_sampler controls the final export rate. + consistent_proportional_sampler: + export_period: 1s # the export period for specifying the expected output rate, it is for rate calculation only, NOT for batch interval. The batch interval can be configured at trace_classification_and_sampling.samplers.export_period, or you can add a batch processor before this. + spans_per_period: 1000 # number of spans per request, the expected rate limit is calculated by dividing this number by export_period. The spans per packet is limited by the max packet size, assuming 1MB limit, and each span with size of 1KB + exponential_smooth: 0.1 # start with small number + initial_estimate_rate: 3000 # number of incomming span rate, just give a reasonable guess. + intermediate_sampler: + export_period: 1s + size_limit: 10000 # the output rate will be at [size_limit, 2*size_limit], i.e. 10000~20000 spans per second + size_limit_type: SpanCount + estimated_sampling: true + exponential_smooth: 0.2 + + selfTelemetry: + exporters: + otlphttp: {} + + + multi_tier: + sidecar: + enable: false + client_side_loadbalancing: false + env: + linux: + spec: + nodeSelector: + kubernetes.io/os: "linux" + windows: + spec: + nodeSelector: + kubernetes.io/os: "windows" + livenessProbe: + initialDelaySeconds: 5 + spec: + image: appdynamics/appdynamics-cloud-apm-collector + mode: sidecar + # based on the perf testing + resources: + limits: + cpu: 200m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + config: + extensions: + health_check: + endpoint: 0.0.0.0:13133 + zpages: + endpoint: 0.0.0.0:55679 + processors: + batch/traces: + send_batch_size: 100 + timeout: 1s + batch/metrics: + send_batch_size: 100 + timeout: 1s + batch/logs: + send_batch_size: 100 + timeout: 1s + exporters: + otlp: + endpoint: appdynamics-otel-collector-service.appdynamics.svc.cluster.local:4317 + tls: + insecure: true + logging: + verbosity: detailed + receivers: + otlp: + protocols: + grpc: + endpoint: localhost:4317 + http: + endpoint: localhost:4318 + service: + extensions: [health_check] + pipelines: + metrics: + receivers: [otlp] + processors: [memory_limiter, batch/metrics] + exporters: [otlp] + traces: + receivers: [otlp] + processors: [memory_limiter, batch/traces] + exporters: [otlp] + logs: + receivers: [otlp] + processors: [memory_limiter, batch/logs] + exporters: [otlp] + tailsampler: + enable: false + os: [linux] + env: + linux: + spec: + nodeSelector: + kubernetes.io/os: "linux" + windows: + nodeSelector: + kubernetes.io/os: "windows" + livenessProbe: + initialDelaySeconds: 5 + spec: + image: appdynamics/appdynamics-cloud-otel-collector:24.4.1-1598 + mode: deployment + # based on the perf testing + resources: + limits: + cpu: 1500m + memory: 1536Mi + requests: + cpu: '1' + memory: 1Gi + config: + extensions: + health_check: + endpoint: 0.0.0.0:13133 + zpages: + endpoint: 0.0.0.0:55679 + processors: + batch/input: + send_batch_size: 500 + batch/traces: + send_batch_size: 1000 + send_batch_max_size: 1000 + batchbybytesize: {} + exporters: + otlphttp: + auth: + authenticator: oauth2client + logging: + verbosity: detailed + service: + extensions: [health_check, oauth2client] + truncated: + trace: + resource: 512 + scope: 512 + span: 512 + spanevent: 512 + metric: + resource: + scope: + datapoint: + log: + resource: + scope: + log: + + + + +filelogReceiverConfig: + includeLogsPath: ["/var/log/*/*/*/*log"] + excludeLogsPath: ["/var/log/pods/*otel-collector*/*/*.log"] + messageParserPattern: "timestamp" + messageParserType: "ABSOLUTE" + diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/.helmignore b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/Chart.yaml new file mode 100644 index 00000000..48a5ddf1 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 24.4.0-1589 +description: A Helm chart for installing otel auto instrumentation CRDs +name: appdynamics-otel-instrumentation +type: application +version: 24.4.0-1589 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/examples/defaults.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/examples/defaults.yaml new file mode 100644 index 00000000..9f2d280e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/examples/defaults.yaml @@ -0,0 +1,2 @@ +spec: + java: \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/examples/oob.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/examples/oob.yaml new file mode 100644 index 00000000..253d802b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/examples/oob.yaml @@ -0,0 +1,9 @@ +spec: + java: + dotnet: + env: + # Required if endpoint is set to 4317. + # Dotnet autoinstrumentation uses http/proto by default + # See https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/blob/888e2cd216c77d12e56b54ee91dafbc4e7452a52/docs/config.md#otlp + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://otel-collector:4318 \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/templates/Instrumentation.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/templates/Instrumentation.yaml new file mode 100644 index 00000000..3d508449 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/templates/Instrumentation.yaml @@ -0,0 +1,36 @@ +{{- define "appdynamics-otel-instrumentation.exporter" -}} +env: + - name: OTEL_EXPORTER_OTLP_PROTOCOL + value: {{ternary "http/protobuf" "grpc" (eq .Values.exporter.protocol "http")}} +exporter: + {{- $scheme := ternary "http://" "https://" .Values.exporter.insecure }} + endpoint: {{$scheme}}{{tpl (dig .Values.exporter.protocol "endpoint" "0.0.0.0:4317" .Values.exporter) .}} +{{- end -}} +{{- define "appdynamics-otel-instrumentation.language.specific.default" -}} +# tracer level configuration - uncomment to enable instrumentation for the language +#java: +{{- $scheme := ternary "http://" "https://" .Values.exporter.insecure }} +python: + env: + - name: OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + value: {{$scheme}}{{tpl (dig "http" "endpoint" "0.0.0.0:4317" .Values.exporter) .}}/v1/traces + - name: OTEL_TRACES_EXPORTER + value: otlp_proto_http +#nodejs: +dotnet: + env: + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{$scheme}}{{tpl (dig "http" "endpoint" "0.0.0.0:4317" .Values.exporter) .}} + - name: OTEL_EXPORTER_OTLP_PROTOCOL + value: http/protobuf +{{- end -}} +--- +apiVersion: opentelemetry.io/v1alpha1 +kind: Instrumentation +metadata: + name: {{ .Values.name | default .Release.Name }} + namespace: {{ .Values.namespace | default .Release.Namespace }} +spec: +{{ $spec := include "appdynamics-otel-instrumentation.exporter" . | fromYaml }} +{{- merge .Values.spec $spec (include "appdynamics-otel-instrumentation.language.specific.default" . | fromYaml) | toYaml | indent 2 }} + diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/templates/_agent_management_and_global_input.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/templates/_agent_management_and_global_input.tpl new file mode 100644 index 00000000..d10761fd --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/templates/_agent_management_and_global_input.tpl @@ -0,0 +1,15 @@ +{{- define "appdynamics-otel-collector.namespace" -}} +{{- if .Values.global.smartAgentInstall -}} +{{- default .Release.Namespace .Values.global.namespace }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} + +{{- define "appdynamics-otel-collector.endpoint" -}} +{{- if (.Values.global.customService).enable -}} +{{.Values.global.customService.name}}.{{.Values.global.customService.namespace}}.svc.cluster.local +{{- else -}} +appdynamics-otel-collector-service.{{ include "appdynamics-otel-collector.namespace" .}}.svc.cluster.local +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/values.schema.json b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/values.schema.json new file mode 100644 index 00000000..7a72a8ec --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/values.schema.json @@ -0,0 +1,76 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "title": "Values", + "additionalProperties": false, + "properties": { + "global": { + "type": "object", + "customService": { + "description": "A custom service which its name and namespace can be configured for user application, shared with collector helm chart.", + "type": "object", + "additionalProperties": false, + "properties": { + "enable" : { + "description": "Whether the custom service will be created, false by default", + "type": "boolean" + }, + "name": { + "description": "The name for the custom service", + "type": "string" + }, + "namespace": { + "description": "The namespace for the custom service", + "type": "string" + } + } + } + }, + "name": { + "description": "name for the opentelemetry instrumentation custom resource.", + "type": "string" + }, + "exporter": { + "description": "exporter config for the instrumentation agent.", + "type": "object", + "properties": { + "protocol": { + "description": "protocol used for communication, could be http or grpc, endpoint will be auto selected for the protocol.", + "type": "string", + "enum": [ + "http", + "grpc" + ] + }, + "insecure": { + "description": "whether use TLS for communication, disable TLS by set it to true.", + "type": "boolean" + }, + "grpc": { + "properties": { + "endpoint": { + "description": "grpc exporter endpoint.", + "type": "string" + } + } + }, + "http": { + "properties": { + "endpoint": { + "description": "http exporter endpoint.", + "type": "string" + } + } + } + } + }, + "spec": { + "description": "instrumentation spec.", + "type": "object" + }, + "enabled" : { + "description": " whether instrumentation enabled.", + "type": "boolean" + } + } +} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/values.yaml new file mode 100644 index 00000000..933f0522 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/values.yaml @@ -0,0 +1,31 @@ +# Default values for appdynamics-otel-instrumentation. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +name: appd-instrumentation +#namespace: appdynamics + +global: + customService: + enable: false + +# exporter configuration - default grpc with insecure +exporter: + protocol: grpc + insecure: true + grpc: + endpoint: "{{ include \"appdynamics-otel-collector.endpoint\" .}}:4317" + http: + endpoint: "{{ include \"appdynamics-otel-collector.endpoint\" .}}:4318" + +spec: + # environment variables (common) + #env: [] + sampler: + type: parentbased_always_on + # common resource attributes, comment out default values which will cause argocd out of sync. + #resource: + # addK8sUIDAttributes: false + # resourceAttributes: {} + # trace propogators + propagators: + - tracecontext \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/Chart.yaml new file mode 100644 index 00000000..82313a08 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +appVersion: 1.0.26 +dependencies: +- name: panoptica + repository: oci://us-docker.pkg.dev/eticloud/panoptica-public-registry + version: 1.218.0 +description: Helm Chart to deploy security collector as a deployment and corresponding + dbconfigs. +home: https://appdynamics.com +icon: https://raw.githubusercontent.com/CiscoDevNet/appdynamics-charts/master/logo.png +maintainers: +- email: support@appdynamics.com + name: AppDynamics +name: appdynamics-security-collector +version: 1.0.26 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/.helmignore b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/.helmignore new file mode 100644 index 00000000..6c5b28ae --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/.helmignore @@ -0,0 +1,27 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +# Ignore helm lint testing ci values +ci/ + +*.mustache \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/Chart.yaml new file mode 100644 index 00000000..98716351 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v2 +appVersion: 1.218.0 +dependencies: +- alias: apiclarity-postgresql + condition: global.isAPISecurityEnabled + name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 11.6.12 +description: Charts for Panoptica deployments. +name: panoptica +type: application +version: 1.218.0 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/README.md b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/README.md new file mode 100644 index 00000000..6921c02e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/README.md @@ -0,0 +1,249 @@ +# panoptica + +![Version: 1.218.0](https://img.shields.io/badge/Version-1.218.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.218.0](https://img.shields.io/badge/AppVersion-1.218.0-informational?style=flat-square) + +Charts for Panoptica deployments. + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| https://charts.bitnami.com/bitnami | apiclarity-postgresql(postgresql) | 11.6.12 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| apiclarity-postgresql.auth.database | string | `"apiclarity"` | | +| apiclarity-postgresql.auth.existingSecret | string | `"apiclarity-postgresql-secret"` | | +| apiclarity-postgresql.containerSecurityContext.enabled | bool | `true` | | +| apiclarity-postgresql.containerSecurityContext.runAsNonRoot | bool | `true` | | +| apiclarity-postgresql.containerSecurityContext.runAsUser | int | `1001` | | +| apiclarity-postgresql.fullnameOverride | string | `"apiclarity-postgresql"` | | +| apiclarity-postgresql.image.pullPolicy | string | `"IfNotPresent"` | | +| apiclarity-postgresql.image.registry | string | `"gcr.io/eticloud/k8sec"` | Image registry, must be set to override the dependency registry. | +| apiclarity-postgresql.image.repository | string | `"bitnami/postgresql"` | | +| apiclarity-postgresql.image.tag | string | `"14.4.0-debian-11-r4"` | | +| apiclarity.affinity | object | `{}` | | +| apiclarity.fuzzer.affinity | object | `{}` | | +| apiclarity.fuzzer.debug | bool | `false` | | +| apiclarity.fuzzer.enabled | bool | `false` | | +| apiclarity.fuzzer.image.pullPolicy | string | `"Always"` | | +| apiclarity.fuzzer.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| apiclarity.fuzzer.image.repository | string | `"scn-dast"` | | +| apiclarity.fuzzer.image.tag | string | `"b0e698ea50aa701d22a1f8fbe549d45c340e0b91"` | | +| apiclarity.fuzzer.labels | object | `{"app":"fuzzer"}` | Configure fuzzer labels | +| apiclarity.fuzzer.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for pod assignment | +| apiclarity.fuzzer.resources.limits.cpu | string | `"200m"` | | +| apiclarity.fuzzer.resources.limits.memory | string | `"1000Mi"` | | +| apiclarity.fuzzer.resources.requests.cpu | string | `"100m"` | | +| apiclarity.fuzzer.resources.requests.memory | string | `"200Mi"` | | +| apiclarity.fuzzer.securityContext.allowPrivilegeEscalation | bool | `false` | | +| apiclarity.fuzzer.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| apiclarity.fuzzer.securityContext.privileged | bool | `false` | | +| apiclarity.fuzzer.securityContext.readOnlyRootFilesystem | bool | `true` | | +| apiclarity.fuzzer.securityContext.runAsGroup | int | `1001` | | +| apiclarity.fuzzer.securityContext.runAsNonRoot | bool | `true` | | +| apiclarity.fuzzer.securityContext.runAsUser | int | `1001` | | +| apiclarity.image.pullPolicy | string | `"IfNotPresent"` | | +| apiclarity.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| apiclarity.image.repository | string | `"apiclarity"` | | +| apiclarity.image.tag | string | `"9a09d167c27046e6d76a96e6e4f248f166b9fc8f"` | | +| apiclarity.imagePullSecrets | list | `[]` | | +| apiclarity.logLevel | string | `"warning"` | Logging level (debug, info, warning, error, fatal, panic). | +| apiclarity.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for pod assignment | +| apiclarity.persistence.accessMode | string | `"ReadWriteOnce"` | | +| apiclarity.persistence.size | string | `"100Mi"` | The storage space that should be claimed from the persistent volume | +| apiclarity.persistence.storageClass | string | `nil` | If defined, storageClassName will be set to the defined storageClass. If set to "-", storageClassName will be set to an empty string (""), which disables dynamic provisioning. If undefined or set to null (the default), no storageClassName spec is set, choosing 'standard' storage class available with the default provisioner (gcd-pd on GKE, hostpath on minikube, etc). | +| apiclarity.podSecurityContext.fsGroup | int | `1000` | | +| apiclarity.resources.limits.cpu | string | `"1000m"` | | +| apiclarity.resources.limits.memory | string | `"1000Mi"` | | +| apiclarity.resources.requests.cpu | string | `"100m"` | | +| apiclarity.resources.requests.memory | string | `"200Mi"` | | +| apiclarity.securityContext.allowPrivilegeEscalation | bool | `false` | | +| apiclarity.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| apiclarity.securityContext.privileged | bool | `false` | | +| apiclarity.securityContext.readOnlyRootFilesystem | bool | `true` | | +| apiclarity.securityContext.runAsGroup | int | `1000` | | +| apiclarity.securityContext.runAsNonRoot | bool | `true` | | +| apiclarity.securityContext.runAsUser | int | `1000` | | +| apiclarity.serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| apiclarity.serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| apiclarity.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| apiclarity.tolerations | list | `[]` | | +| apiclarity.traceSource.external | bool | `false` | Indicates whether external GWs supply traces. | +| apiclarity.traceSource.istio | bool | `false` | Indicates whether istio supply traces. | +| apiclarity.traceWasmFilterSHA256 | string | `"5f48a298d47422f6fb8e03b5c856fae5c4aaab60b8b9e9f28a13ca34d22bf0b7"` | | +| busybox.image.pullPolicy | string | `"IfNotPresent"` | | +| busybox.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| busybox.image.repository | string | `"curlimages/curl"` | | +| busybox.image.tag | string | `"latest"` | | +| busybox.securityContext.allowPrivilegeEscalation | bool | `false` | | +| busybox.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| busybox.securityContext.privileged | bool | `false` | | +| busybox.securityContext.readOnlyRootFilesystem | bool | `true` | | +| busybox.securityContext.runAsGroup | int | `1001` | | +| busybox.securityContext.runAsNonRoot | bool | `true` | | +| busybox.securityContext.runAsUser | int | `1001` | | +| controller.affinity | object | `{}` | | +| controller.agentID | string | `""` | [Required] Controller identification, should be extracted from SaaS after cluster creation. | +| controller.autoscaling.enabled | bool | `true` | | +| controller.autoscaling.maxReplicas | int | `5` | | +| controller.autoscaling.minReplicas | int | `1` | | +| controller.autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| controller.fullnameOverride | string | `"portshift-agent"` | | +| controller.image.pullPolicy | string | `"IfNotPresent"` | | +| controller.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| controller.image.repository | string | `"k8s_agent"` | | +| controller.image.tag | string | `"fdb16f4d5c28fef6538d01b07ed2520bc9253809"` | | +| controller.imagePullSecrets | list | `[]` | | +| controller.logLevel | string | `"warning"` | Logging level (debug, info, warning, error, fatal, panic). | +| controller.nameOverride | string | `"portshift-agent"` | | +| controller.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for controller pod assignment | +| controller.pdb.create | bool | `true` | | +| controller.pdb.minAvailable | int | `1` | | +| controller.persistence.accessMode | string | `"ReadWriteOnce"` | | +| controller.persistence.enabled | bool | `false` | Enable persistence using Persistent Volume Claims | +| controller.persistence.pvcSuffix | string | `"pvc-fdb16f4d5c28fef6538d01b07ed2520bc9253809"` | | +| controller.persistence.size | string | `"100Mi"` | The storage space that should be claimed from the persistent volume | +| controller.persistence.storageClass | string | `nil` | If defined, storageClassName will be set to the defined storageClass. If set to "-", storageClassName will be set to an empty string (""), which disables dynamic provisioning. If undefined or set to null (the default), no storageClassName spec is set, choosing 'standard' storage class available with the default provisioner (gcd-pd on GKE, hostpath on minikube, etc). | +| controller.podSecurityContext.fsGroup | int | `1001` | | +| controller.replicaCount | int | `1` | Configure controller replica count number in case autoscaling is disabled. | +| controller.resources.requests.cpu | string | `"500m"` | | +| controller.resources.requests.memory | string | `"2048Mi"` | | +| controller.secret.existingSecret | string | `""` | Existing secret that contains shared secret used by the controller to communicate with the SaaS. | +| controller.secret.sharedSecret | string | `""` | [Required if controller.existingSecret isn't set] Shared secret used by the controller to communicate with the SaaS, should be extracted from SaaS after cluster creation. | +| controller.secret.sharedSecretKey | string | `""` | Shared secret key is the key of the shared secret, default: SHARED_SECRET. | +| controller.securityContext.allowPrivilegeEscalation | bool | `false` | | +| controller.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| controller.securityContext.privileged | bool | `false` | | +| controller.securityContext.readOnlyRootFilesystem | bool | `true` | | +| controller.securityContext.runAsGroup | int | `1001` | | +| controller.securityContext.runAsNonRoot | bool | `true` | | +| controller.securityContext.runAsUser | int | `1001` | | +| controller.service.type | string | `"ClusterIP"` | | +| controller.serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| controller.serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| controller.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| controller.tolerations | list | `[]` | | +| dnsDetector.image.pullPolicy | string | `"IfNotPresent"` | | +| dnsDetector.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| dnsDetector.image.repository | string | `"gopassivedns"` | | +| dnsDetector.image.tag | string | `"0c7330b51a07cdebe13e57b1d1a33134cbbe04ce"` | | +| dnsDetector.resources.limits.cpu | string | `"200m"` | | +| dnsDetector.resources.limits.memory | string | `"100Mi"` | | +| dnsDetector.resources.requests.cpu | string | `"20m"` | | +| dnsDetector.resources.requests.memory | string | `"50Mi"` | | +| global.autoLabelEnabled | bool | `false` | Indicates whether auto label is enabled. If true, new namespaces will be labeled with the protection label. | +| global.cdValidation | bool | `false` | Indicates whether to identity pods whose templates originated from the Panoptica CD plugin. See `CD Pod template` section in https://panoptica.readme.io/docs/deploy-on-a-kubernetes-cluster for more info. | +| global.ciImageSignatureValidation | bool | `false` | Indicates whether to identity pods only if all images are signed by a trusted signer. See https://panoptica.readme.io/docs/trusted-signers for more info. | +| global.ciImageValidation | bool | `false` | Indicates whether to identity pods only if all image hashes are known to Panoptica. See `CI image hash validation` section in https://panoptica.readme.io/docs/deploy-on-a-kubernetes-cluster for more info. | +| global.connectionFailPolicyAllow | bool | `true` | If false, connections on protected namespaces will be blocked if the controller is not responding. | +| global.dummyPlaceHolderForTest | bool | `false` | Placeholder used for tests. | +| global.enableTlsInspection | bool | `false` | Indicates whether TLS inspection is enabled. If true, the controller will be able to decrypt and re-encrypt HTTPS traffic for connections to be inspected via layer 7 attributes. | +| global.environmentFailurePolicyAllow | bool | `true` | If false, pods creation on protected namespaces will be blocked if the controller is not responding. | +| global.extraLabels | object | `{}` | Allow labelling resources with custom key/value pairs. | +| global.httpProxy | string | `""` | Proxy address to use for HTTP request if needed. | +| global.httpsProxy | string | `""` | Proxy address to use for HTTPs request if needed. In most cases, this is the same as `httpProxy`. | +| global.isAPISecurityEnabled | bool | `false` | Indicates whether API security is enabled. | +| global.isConnectionEnforcementEnabled | bool | `false` | Indicates whether connection enforcement is enabled. If true, make sure istio is installed by using panoptica istio chart or an upstream istio is already installed. | +| global.isContainerSecurityEnabled | bool | `true` | Indicates whether kubernetes security is enabled. | +| global.isExternalCaEnabled | bool | `false` | Indicates whether istio should provision workload certificates using a custom certificate authority that integrates with the Kubernetes CSR API. | +| global.isOpenShift | bool | `false` | Indicates whether installed in an OpenShift environment. | +| global.isSSHMonitorEnabled | bool | `true` | Indicates whether SSH monitoring is enabled. | +| global.k8sCisBenchmarkEnabled | bool | `true` | Indicates whether K8s CIS benchmark is enabled. | +| global.k8sEventsEnabled | bool | `true` | Indicates whether K8s Events monitoring is enabled. | +| global.kubeVersionOverride | string | `""` | Override detected cluster version. | +| global.mgmtHostname | string | `""` | Panoptica SaaS URL. Used to override default URL for local testing. | +| global.preserveOriginalSourceIp | bool | `false` | Indicates whether the controller should preserve the original source ip of inbound connections. | +| global.productNameOverride | string | `"portshift"` | Override product name. Defaults to chart name. | +| global.registry | string | `"gcr.io/eticloud/k8sec"` | Registry for the Panoptica images. If replaced with a local registry need to make sure all images are pulled into the local registry. | +| global.restrictRegistries | bool | `false` | Indicates whether to identity pods only if all images are pulled from trusted registries. See `Restrict Registries` section in https://panoptica.readme.io/docs/deploy-on-a-kubernetes-cluster for more info. | +| global.sendTelemetriesIntervalSec | int | `30` | Configures telemetry frequency (in seconds) for reporting duration. | +| global.tokenInjectionEnabled | bool | `false` | Indicates whether token injection feature is enabled. If true, make sure vault is installed by using panoptica vault chart. | +| global.validateDeployerPolicy | bool | `false` | Indicates whether Deployer Policy enforcement is enabled. | +| imageAnalysis.cisDockerBenchmark.enabled | bool | `false` | | +| imageAnalysis.cisDockerBenchmark.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| imageAnalysis.cisDockerBenchmark.image.repository | string | `"cis-docker-benchmark"` | | +| imageAnalysis.cisDockerBenchmark.image.tag | string | `"a281d02d480ba3fc815d176731fa9412fe872ad3"` | | +| imageAnalysis.cisDockerBenchmark.podSecurityContext.fsGroup | int | `1001` | | +| imageAnalysis.cisDockerBenchmark.resources.limits.cpu | string | `"1000m"` | | +| imageAnalysis.cisDockerBenchmark.resources.limits.memory | string | `"1000Mi"` | | +| imageAnalysis.cisDockerBenchmark.resources.requests.cpu | string | `"50m"` | | +| imageAnalysis.cisDockerBenchmark.resources.requests.memory | string | `"50Mi"` | | +| imageAnalysis.cisDockerBenchmark.securityContext.allowPrivilegeEscalation | bool | `false` | | +| imageAnalysis.cisDockerBenchmark.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| imageAnalysis.cisDockerBenchmark.securityContext.privileged | bool | `false` | | +| imageAnalysis.cisDockerBenchmark.securityContext.readOnlyRootFilesystem | bool | `true` | | +| imageAnalysis.cisDockerBenchmark.securityContext.runAsGroup | int | `1001` | | +| imageAnalysis.cisDockerBenchmark.securityContext.runAsNonRoot | bool | `true` | | +| imageAnalysis.cisDockerBenchmark.securityContext.runAsUser | int | `1001` | | +| imageAnalysis.jobDefaultNamespace | string | `""` | Scanner jobs namespace. If left blank, the scanner jobs will run in release namespace. If set, the scanner jobs will run in the given namespace unless the image requires image pull secrets which are located in a target pod | +| imageAnalysis.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for controller pod assignment | +| imageAnalysis.parallelScanners | int | `4` | The max number of scanner jobs that will run in the cluster in parallel for image analysis in total | +| imageAnalysis.registry.skipVerifyTlS | string | `"false"` | | +| imageAnalysis.registry.useHTTP | string | `"false"` | | +| imageAnalysis.sbom.enabled | bool | `true` | | +| imageAnalysis.sbom.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| imageAnalysis.sbom.image.repository | string | `"image-analyzer"` | | +| imageAnalysis.sbom.image.tag | string | `"5f969c4535b52368ff7e288f6c9a2ce8bea019b0"` | | +| imageAnalysis.sbom.podSecurityContext.fsGroup | int | `1001` | | +| imageAnalysis.sbom.resources.limits.cpu | string | `"1000m"` | | +| imageAnalysis.sbom.resources.limits.memory | string | `"2000Mi"` | | +| imageAnalysis.sbom.resources.requests.cpu | string | `"50m"` | | +| imageAnalysis.sbom.resources.requests.memory | string | `"50Mi"` | | +| imageAnalysis.sbom.securityContext.allowPrivilegeEscalation | bool | `false` | | +| imageAnalysis.sbom.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| imageAnalysis.sbom.securityContext.privileged | bool | `false` | | +| imageAnalysis.sbom.securityContext.readOnlyRootFilesystem | bool | `true` | | +| imageAnalysis.sbom.securityContext.runAsGroup | int | `1001` | | +| imageAnalysis.sbom.securityContext.runAsNonRoot | bool | `true` | | +| imageAnalysis.sbom.securityContext.runAsUser | int | `1001` | | +| imageAnalysis.tolerations | list | `[]` | | +| istio.expansion.enabled | bool | `false` | | +| istio.global.alreadyInstalled | bool | `false` | Indicates whether istio is already installed and not by Panoptica charts. | +| istio.global.serviceDiscoveryIsolationEnabled | bool | `false` | | +| istio.global.version | string | `"1.19.0"` | Indicates what version of istio is running, change only if `alreadyInstalled` is set to true. | +| k8sCISBenchmark.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| k8sCISBenchmark.image.repository | string | `"k8s-cis-benchmark"` | | +| k8sCISBenchmark.image.tag | string | `"f5b0490258b1cb87ce6eddc2a3083482135dcf5c"` | | +| k8sCISBenchmark.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for pod assignment | +| kafkaAuthzInjector.image.pullPolicy | string | `"Always"` | | +| kafkaAuthzInjector.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| kafkaAuthzInjector.image.repository | string | `"kafka-authz"` | | +| kafkaAuthzInjector.image.tag | string | `"e647ba66cf10897ee6e07a3d6d81b2148d0a47be"` | | +| kafkaAuthzInjector.securityContext.allowPrivilegeEscalation | bool | `false` | | +| kafkaAuthzInjector.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| kafkaAuthzInjector.securityContext.privileged | bool | `false` | | +| kafkaAuthzInjector.securityContext.readOnlyRootFilesystem | bool | `true` | | +| kafkaAuthzInjector.securityContext.runAsGroup | int | `1001` | | +| kafkaAuthzInjector.securityContext.runAsNonRoot | bool | `true` | | +| kafkaAuthzInjector.securityContext.runAsUser | int | `1001` | | +| kubectl.image.pullPolicy | string | `"IfNotPresent"` | | +| kubectl.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| kubectl.image.repository | string | `"kubectl"` | | +| kubectl.image.tag | string | `"v1.27.1"` | | +| seccompInstaller.serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| seccompInstaller.serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| seccompInstaller.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| upgrader.image.pullPolicy | string | `"Always"` | | +| upgrader.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for pod assignment | +| upgrader.podSecurityContext.fsGroup | int | `1001` | | +| upgrader.resources.limits.cpu | string | `"1000m"` | | +| upgrader.resources.limits.memory | string | `"1000Mi"` | | +| upgrader.resources.requests.cpu | string | `"50m"` | | +| upgrader.resources.requests.memory | string | `"50Mi"` | | +| upgrader.securityContext.allowPrivilegeEscalation | bool | `false` | | +| upgrader.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| upgrader.securityContext.privileged | bool | `false` | | +| upgrader.securityContext.readOnlyRootFilesystem | bool | `true` | | +| upgrader.securityContext.runAsGroup | int | `1001` | | +| upgrader.securityContext.runAsNonRoot | bool | `true` | | +| upgrader.securityContext.runAsUser | int | `1001` | | +| upgrader.tolerations | list | `[]` | | +| vaultEnv.image.registry | string | `""` | Image registry, used to override global.registry if needed. | +| vaultEnv.image.repository | string | `"bank-vaults/vault-env"` | | +| vaultEnv.image.tag | string | `"v1.21.0"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/.helmignore b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/.helmignore new file mode 100644 index 00000000..f0c13194 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/Chart.yaml new file mode 100644 index 00000000..c6117503 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/Chart.yaml @@ -0,0 +1,30 @@ +annotations: + category: Database +apiVersion: v2 +appVersion: 14.4.0 +dependencies: +- name: common + repository: https://charts.bitnami.com/bitnami + version: 1.x.x +description: PostgreSQL (Postgres) is an open source object-relational database known + for reliability and data integrity. ACID-compliant, it supports foreign keys, joins, + views, triggers and stored procedures. +home: https://github.com/bitnami/charts/tree/master/bitnami/postgresql +icon: https://bitnami.com/assets/stacks/postgresql/img/postgresql-stack-220x234.png +keywords: +- postgresql +- postgres +- database +- sql +- replication +- cluster +maintainers: +- name: Bitnami + url: https://github.com/bitnami/charts +- email: cedric@desaintmartin.fr + name: desaintmartin +name: postgresql +sources: +- https://github.com/bitnami/bitnami-docker-postgresql +- https://www.postgresql.org/ +version: 11.6.12 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/README.md b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/README.md new file mode 100644 index 00000000..ec97a8fa --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/README.md @@ -0,0 +1,672 @@ + + +# PostgreSQL packaged by Bitnami + +PostgreSQL (Postgres) is an open source object-relational database known for reliability and data integrity. ACID-compliant, it supports foreign keys, joins, views, triggers and stored procedures. + +[Overview of PostgreSQL](http://www.postgresql.org) + +Trademarks: This software listing is packaged by Bitnami. The respective trademarks mentioned in the offering are owned by the respective companies, and use of them does not imply any affiliation or endorsement. + +## TL;DR + +```bash +helm repo add bitnami https://charts.bitnami.com/bitnami +helm install my-release bitnami/postgresql +``` + +## Introduction + +This chart bootstraps a [PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) deployment on a [Kubernetes](https://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +For HA, please see [this repo](https://github.com/bitnami/charts/tree/master/bitnami/postgresql-ha) + +Bitnami charts can be used with [Kubeapps](https://kubeapps.dev/) for deployment and management of Helm Charts in clusters. + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.2.0+ +- PV provisioner support in the underlying infrastructure + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```bash +helm install my-release bitnami/postgresql +``` + +The command deploys PostgreSQL on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. + +> **Tip**: List all releases using `helm list` + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```console +helm delete my-release +``` + +The command removes all the Kubernetes components but PVC's associated with the chart and deletes the release. + +To delete the PVC's associated with `my-release`: + +```bash +kubectl delete pvc -l release=my-release +``` + +> **Note**: Deleting the PVC's will delete postgresql data as well. Please be cautious before doing it. + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | +| `global.postgresql.auth.postgresPassword` | Password for the "postgres" admin user (overrides `auth.postgresPassword`) | `""` | +| `global.postgresql.auth.username` | Name for a custom user to create (overrides `auth.username`) | `""` | +| `global.postgresql.auth.password` | Password for the custom user to create (overrides `auth.password`) | `""` | +| `global.postgresql.auth.database` | Name for a custom database to create (overrides `auth.database`) | `""` | +| `global.postgresql.auth.existingSecret` | Name of existing secret to use for PostgreSQL credentials (overrides `auth.existingSecret`). | `""` | +| `global.postgresql.auth.secretKeys.adminPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.adminPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. | `""` | +| `global.postgresql.auth.secretKeys.userPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.userPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. | `""` | +| `global.postgresql.auth.secretKeys.replicationPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.replicationPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. | `""` | +| `global.postgresql.service.ports.postgresql` | PostgreSQL service port (overrides `service.ports.postgresql`) | `""` | + + +### Common parameters + +| Name | Description | Value | +| ------------------------ | -------------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Override Kubernetes version | `""` | +| `nameOverride` | String to partially override common.names.fullname template (will maintain the release name) | `""` | +| `fullnameOverride` | String to fully override common.names.fullname template | `""` | +| `clusterDomain` | Kubernetes Cluster Domain | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release (evaluated as a template) | `[]` | +| `commonLabels` | Add labels to all the deployed resources | `{}` | +| `commonAnnotations` | Add annotations to all the deployed resources | `{}` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the statefulset | `["sleep"]` | +| `diagnosticMode.args` | Args to override all containers in the statefulset | `["infinity"]` | + + +### PostgreSQL common parameters + +| Name | Description | Value | +| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | +| `image.registry` | PostgreSQL image registry | `docker.io` | +| `image.repository` | PostgreSQL image repository | `bitnami/postgresql` | +| `image.tag` | PostgreSQL image tag (immutable tags are recommended) | `14.4.0-debian-11-r4` | +| `image.pullPolicy` | PostgreSQL image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify image pull secrets | `[]` | +| `image.debug` | Specify if debug values should be set | `false` | +| `auth.enablePostgresUser` | Assign a password to the "postgres" admin user. Otherwise, remote access will be blocked for this user | `true` | +| `auth.postgresPassword` | Password for the "postgres" admin user. Ignored if `auth.existingSecret` with key `postgres-password` is provided | `""` | +| `auth.username` | Name for a custom user to create | `""` | +| `auth.password` | Password for the custom user to create. Ignored if `auth.existingSecret` with key `password` is provided | `""` | +| `auth.database` | Name for a custom database to create | `""` | +| `auth.replicationUsername` | Name of the replication user | `repl_user` | +| `auth.replicationPassword` | Password for the replication user. Ignored if `auth.existingSecret` with key `replication-password` is provided | `""` | +| `auth.existingSecret` | Name of existing secret to use for PostgreSQL credentials. `auth.postgresPassword`, `auth.password`, and `auth.replicationPassword` will be ignored and picked up from this secret. The secret might also contains the key `ldap-password` if LDAP is enabled. `ldap.bind_password` will be ignored and picked from this secret in this case. | `""` | +| `auth.secretKeys.adminPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. | `postgres-password` | +| `auth.secretKeys.userPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. | `password` | +| `auth.secretKeys.replicationPasswordKey` | Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. | `replication-password` | +| `auth.usePasswordFiles` | Mount credentials as a files instead of using an environment variable | `false` | +| `architecture` | PostgreSQL architecture (`standalone` or `replication`) | `standalone` | +| `replication.synchronousCommit` | Set synchronous commit mode. Allowed values: `on`, `remote_apply`, `remote_write`, `local` and `off` | `off` | +| `replication.numSynchronousReplicas` | Number of replicas that will have synchronous replication. Note: Cannot be greater than `readReplicas.replicaCount`. | `0` | +| `replication.applicationName` | Cluster application name. Useful for advanced replication settings | `my_application` | +| `containerPorts.postgresql` | PostgreSQL container port | `5432` | +| `audit.logHostname` | Log client hostnames | `false` | +| `audit.logConnections` | Add client log-in operations to the log file | `false` | +| `audit.logDisconnections` | Add client log-outs operations to the log file | `false` | +| `audit.pgAuditLog` | Add operations to log using the pgAudit extension | `""` | +| `audit.pgAuditLogCatalog` | Log catalog using pgAudit | `off` | +| `audit.clientMinMessages` | Message log level to share with the user | `error` | +| `audit.logLinePrefix` | Template for log line prefix (default if not set) | `""` | +| `audit.logTimezone` | Timezone for the log timestamps | `""` | +| `ldap.enabled` | Enable LDAP support | `false` | +| `ldap.server` | IP address or name of the LDAP server. | `""` | +| `ldap.port` | Port number on the LDAP server to connect to | `""` | +| `ldap.prefix` | String to prepend to the user name when forming the DN to bind | `""` | +| `ldap.suffix` | String to append to the user name when forming the DN to bind | `""` | +| `ldap.basedn` | Root DN to begin the search for the user in | `""` | +| `ldap.binddn` | DN of user to bind to LDAP | `""` | +| `ldap.bindpw` | Password for the user to bind to LDAP | `""` | +| `ldap.searchAttribute` | Attribute to match against the user name in the search | `""` | +| `ldap.searchFilter` | The search filter to use when doing search+bind authentication | `""` | +| `ldap.scheme` | Set to `ldaps` to use LDAPS | `""` | +| `ldap.tls.enabled` | Se to true to enable TLS encryption | `false` | +| `ldap.uri` | LDAP URL beginning in the form `ldap[s]://host[:port]/basedn`. If provided, all the other LDAP parameters will be ignored. | `""` | +| `postgresqlDataDir` | PostgreSQL data dir folder | `/bitnami/postgresql/data` | +| `postgresqlSharedPreloadLibraries` | Shared preload libraries (comma-separated list) | `pgaudit` | +| `shmVolume.enabled` | Enable emptyDir volume for /dev/shm for PostgreSQL pod(s) | `true` | +| `shmVolume.sizeLimit` | Set this to enable a size limit on the shm tmpfs | `""` | +| `tls.enabled` | Enable TLS traffic support | `false` | +| `tls.autoGenerated` | Generate automatically self-signed TLS certificates | `false` | +| `tls.preferServerCiphers` | Whether to use the server's TLS cipher preferences rather than the client's | `true` | +| `tls.certificatesSecret` | Name of an existing secret that contains the certificates | `""` | +| `tls.certFilename` | Certificate filename | `""` | +| `tls.certKeyFilename` | Certificate key filename | `""` | +| `tls.certCAFilename` | CA Certificate filename | `""` | +| `tls.crlFilename` | File containing a Certificate Revocation List | `""` | + + +### PostgreSQL Primary parameters + +| Name | Description | Value | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------- | +| `primary.configuration` | PostgreSQL Primary main configuration to be injected as ConfigMap | `""` | +| `primary.pgHbaConfiguration` | PostgreSQL Primary client authentication configuration | `""` | +| `primary.existingConfigmap` | Name of an existing ConfigMap with PostgreSQL Primary configuration | `""` | +| `primary.extendedConfiguration` | Extended PostgreSQL Primary configuration (appended to main or default configuration) | `""` | +| `primary.existingExtendedConfigmap` | Name of an existing ConfigMap with PostgreSQL Primary extended configuration | `""` | +| `primary.initdb.args` | PostgreSQL initdb extra arguments | `""` | +| `primary.initdb.postgresqlWalDir` | Specify a custom location for the PostgreSQL transaction log | `""` | +| `primary.initdb.scripts` | Dictionary of initdb scripts | `{}` | +| `primary.initdb.scriptsConfigMap` | ConfigMap with scripts to be run at first boot | `""` | +| `primary.initdb.scriptsSecret` | Secret with scripts to be run at first boot (in case it contains sensitive information) | `""` | +| `primary.initdb.user` | Specify the PostgreSQL username to execute the initdb scripts | `""` | +| `primary.initdb.password` | Specify the PostgreSQL password to execute the initdb scripts | `""` | +| `primary.standby.enabled` | Whether to enable current cluster's primary as standby server of another cluster or not | `false` | +| `primary.standby.primaryHost` | The Host of replication primary in the other cluster | `""` | +| `primary.standby.primaryPort` | The Port of replication primary in the other cluster | `""` | +| `primary.extraEnvVars` | Array with extra environment variables to add to PostgreSQL Primary nodes | `[]` | +| `primary.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for PostgreSQL Primary nodes | `""` | +| `primary.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for PostgreSQL Primary nodes | `""` | +| `primary.command` | Override default container command (useful when using custom images) | `[]` | +| `primary.args` | Override default container args (useful when using custom images) | `[]` | +| `primary.livenessProbe.enabled` | Enable livenessProbe on PostgreSQL Primary containers | `true` | +| `primary.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `primary.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `primary.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `primary.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `primary.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `primary.readinessProbe.enabled` | Enable readinessProbe on PostgreSQL Primary containers | `true` | +| `primary.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `primary.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `primary.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `primary.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `primary.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `primary.startupProbe.enabled` | Enable startupProbe on PostgreSQL Primary containers | `false` | +| `primary.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `30` | +| `primary.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `primary.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` | +| `primary.startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` | +| `primary.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `primary.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `primary.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `primary.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `primary.lifecycleHooks` | for the PostgreSQL Primary container to automate configuration before or after startup | `{}` | +| `primary.resources.limits` | The resources limits for the PostgreSQL Primary containers | `{}` | +| `primary.resources.requests.memory` | The requested memory for the PostgreSQL Primary containers | `256Mi` | +| `primary.resources.requests.cpu` | The requested cpu for the PostgreSQL Primary containers | `250m` | +| `primary.podSecurityContext.enabled` | Enable security context | `true` | +| `primary.podSecurityContext.fsGroup` | Group ID for the pod | `1001` | +| `primary.containerSecurityContext.enabled` | Enable container security context | `true` | +| `primary.containerSecurityContext.runAsUser` | User ID for the container | `1001` | +| `primary.hostAliases` | PostgreSQL primary pods host aliases | `[]` | +| `primary.hostNetwork` | Specify if host network should be enabled for PostgreSQL pod (postgresql primary) | `false` | +| `primary.hostIPC` | Specify if host IPC should be enabled for PostgreSQL pod (postgresql primary) | `false` | +| `primary.labels` | Map of labels to add to the statefulset (postgresql primary) | `{}` | +| `primary.annotations` | Annotations for PostgreSQL primary pods | `{}` | +| `primary.podLabels` | Map of labels to add to the pods (postgresql primary) | `{}` | +| `primary.podAnnotations` | Map of annotations to add to the pods (postgresql primary) | `{}` | +| `primary.podAffinityPreset` | PostgreSQL primary pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `primary.podAntiAffinityPreset` | PostgreSQL primary pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `primary.nodeAffinityPreset.type` | PostgreSQL primary node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `primary.nodeAffinityPreset.key` | PostgreSQL primary node label key to match Ignored if `primary.affinity` is set. | `""` | +| `primary.nodeAffinityPreset.values` | PostgreSQL primary node label values to match. Ignored if `primary.affinity` is set. | `[]` | +| `primary.affinity` | Affinity for PostgreSQL primary pods assignment | `{}` | +| `primary.nodeSelector` | Node labels for PostgreSQL primary pods assignment | `{}` | +| `primary.tolerations` | Tolerations for PostgreSQL primary pods assignment | `[]` | +| `primary.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `primary.priorityClassName` | Priority Class to use for each pod (postgresql primary) | `""` | +| `primary.schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` | +| `primary.terminationGracePeriodSeconds` | Seconds PostgreSQL primary pod needs to terminate gracefully | `""` | +| `primary.updateStrategy.type` | PostgreSQL Primary statefulset strategy type | `RollingUpdate` | +| `primary.updateStrategy.rollingUpdate` | PostgreSQL Primary statefulset rolling update configuration parameters | `{}` | +| `primary.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the PostgreSQL Primary container(s) | `[]` | +| `primary.extraVolumes` | Optionally specify extra list of additional volumes for the PostgreSQL Primary pod(s) | `[]` | +| `primary.sidecars` | Add additional sidecar containers to the PostgreSQL Primary pod(s) | `[]` | +| `primary.initContainers` | Add additional init containers to the PostgreSQL Primary pod(s) | `[]` | +| `primary.extraPodSpec` | Optionally specify extra PodSpec for the PostgreSQL Primary pod(s) | `{}` | +| `primary.service.type` | Kubernetes Service type | `ClusterIP` | +| `primary.service.ports.postgresql` | PostgreSQL service port | `5432` | +| `primary.service.nodePorts.postgresql` | Node port for PostgreSQL | `""` | +| `primary.service.clusterIP` | Static clusterIP or None for headless services | `""` | +| `primary.service.annotations` | Annotations for PostgreSQL primary service | `{}` | +| `primary.service.loadBalancerIP` | Load balancer IP if service type is `LoadBalancer` | `""` | +| `primary.service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | +| `primary.service.loadBalancerSourceRanges` | Addresses that are allowed when service is LoadBalancer | `[]` | +| `primary.service.extraPorts` | Extra ports to expose in the PostgreSQL primary service | `[]` | +| `primary.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `primary.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `primary.persistence.enabled` | Enable PostgreSQL Primary data persistence using PVC | `true` | +| `primary.persistence.existingClaim` | Name of an existing PVC to use | `""` | +| `primary.persistence.mountPath` | The path the volume will be mounted at | `/bitnami/postgresql` | +| `primary.persistence.subPath` | The subdirectory of the volume to mount to | `""` | +| `primary.persistence.storageClass` | PVC Storage Class for PostgreSQL Primary data volume | `""` | +| `primary.persistence.accessModes` | PVC Access Mode for PostgreSQL volume | `["ReadWriteOnce"]` | +| `primary.persistence.size` | PVC Storage Request for PostgreSQL volume | `8Gi` | +| `primary.persistence.annotations` | Annotations for the PVC | `{}` | +| `primary.persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` | +| `primary.persistence.dataSource` | Custom PVC data source | `{}` | + + +### PostgreSQL read only replica parameters + +| Name | Description | Value | +| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------- | +| `readReplicas.replicaCount` | Number of PostgreSQL read only replicas | `1` | +| `readReplicas.extraEnvVars` | Array with extra environment variables to add to PostgreSQL read only nodes | `[]` | +| `readReplicas.extraEnvVarsCM` | Name of existing ConfigMap containing extra env vars for PostgreSQL read only nodes | `""` | +| `readReplicas.extraEnvVarsSecret` | Name of existing Secret containing extra env vars for PostgreSQL read only nodes | `""` | +| `readReplicas.command` | Override default container command (useful when using custom images) | `[]` | +| `readReplicas.args` | Override default container args (useful when using custom images) | `[]` | +| `readReplicas.livenessProbe.enabled` | Enable livenessProbe on PostgreSQL read only containers | `true` | +| `readReplicas.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `30` | +| `readReplicas.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `readReplicas.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `readReplicas.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `readReplicas.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `readReplicas.readinessProbe.enabled` | Enable readinessProbe on PostgreSQL read only containers | `true` | +| `readReplicas.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `readReplicas.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `readReplicas.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `readReplicas.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `readReplicas.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `readReplicas.startupProbe.enabled` | Enable startupProbe on PostgreSQL read only containers | `false` | +| `readReplicas.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `30` | +| `readReplicas.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `readReplicas.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` | +| `readReplicas.startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` | +| `readReplicas.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `readReplicas.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `readReplicas.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `readReplicas.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `readReplicas.lifecycleHooks` | for the PostgreSQL read only container to automate configuration before or after startup | `{}` | +| `readReplicas.resources.limits` | The resources limits for the PostgreSQL read only containers | `{}` | +| `readReplicas.resources.requests.memory` | The requested memory for the PostgreSQL read only containers | `256Mi` | +| `readReplicas.resources.requests.cpu` | The requested cpu for the PostgreSQL read only containers | `250m` | +| `readReplicas.podSecurityContext.enabled` | Enable security context | `true` | +| `readReplicas.podSecurityContext.fsGroup` | Group ID for the pod | `1001` | +| `readReplicas.containerSecurityContext.enabled` | Enable container security context | `true` | +| `readReplicas.containerSecurityContext.runAsUser` | User ID for the container | `1001` | +| `readReplicas.hostAliases` | PostgreSQL read only pods host aliases | `[]` | +| `readReplicas.hostNetwork` | Specify if host network should be enabled for PostgreSQL pod (PostgreSQL read only) | `false` | +| `readReplicas.hostIPC` | Specify if host IPC should be enabled for PostgreSQL pod (postgresql primary) | `false` | +| `readReplicas.labels` | Map of labels to add to the statefulset (PostgreSQL read only) | `{}` | +| `readReplicas.annotations` | Annotations for PostgreSQL read only pods | `{}` | +| `readReplicas.podLabels` | Map of labels to add to the pods (PostgreSQL read only) | `{}` | +| `readReplicas.podAnnotations` | Map of annotations to add to the pods (PostgreSQL read only) | `{}` | +| `readReplicas.podAffinityPreset` | PostgreSQL read only pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `readReplicas.podAntiAffinityPreset` | PostgreSQL read only pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `readReplicas.nodeAffinityPreset.type` | PostgreSQL read only node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `readReplicas.nodeAffinityPreset.key` | PostgreSQL read only node label key to match Ignored if `primary.affinity` is set. | `""` | +| `readReplicas.nodeAffinityPreset.values` | PostgreSQL read only node label values to match. Ignored if `primary.affinity` is set. | `[]` | +| `readReplicas.affinity` | Affinity for PostgreSQL read only pods assignment | `{}` | +| `readReplicas.nodeSelector` | Node labels for PostgreSQL read only pods assignment | `{}` | +| `readReplicas.tolerations` | Tolerations for PostgreSQL read only pods assignment | `[]` | +| `readReplicas.topologySpreadConstraints` | Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template | `[]` | +| `readReplicas.priorityClassName` | Priority Class to use for each pod (PostgreSQL read only) | `""` | +| `readReplicas.schedulerName` | Use an alternate scheduler, e.g. "stork". | `""` | +| `readReplicas.terminationGracePeriodSeconds` | Seconds PostgreSQL read only pod needs to terminate gracefully | `""` | +| `readReplicas.updateStrategy.type` | PostgreSQL read only statefulset strategy type | `RollingUpdate` | +| `readReplicas.updateStrategy.rollingUpdate` | PostgreSQL read only statefulset rolling update configuration parameters | `{}` | +| `readReplicas.extraVolumeMounts` | Optionally specify extra list of additional volumeMounts for the PostgreSQL read only container(s) | `[]` | +| `readReplicas.extraVolumes` | Optionally specify extra list of additional volumes for the PostgreSQL read only pod(s) | `[]` | +| `readReplicas.sidecars` | Add additional sidecar containers to the PostgreSQL read only pod(s) | `[]` | +| `readReplicas.initContainers` | Add additional init containers to the PostgreSQL read only pod(s) | `[]` | +| `readReplicas.extraPodSpec` | Optionally specify extra PodSpec for the PostgreSQL read only pod(s) | `{}` | +| `readReplicas.service.type` | Kubernetes Service type | `ClusterIP` | +| `readReplicas.service.ports.postgresql` | PostgreSQL service port | `5432` | +| `readReplicas.service.nodePorts.postgresql` | Node port for PostgreSQL | `""` | +| `readReplicas.service.clusterIP` | Static clusterIP or None for headless services | `""` | +| `readReplicas.service.annotations` | Annotations for PostgreSQL read only service | `{}` | +| `readReplicas.service.loadBalancerIP` | Load balancer IP if service type is `LoadBalancer` | `""` | +| `readReplicas.service.externalTrafficPolicy` | Enable client source IP preservation | `Cluster` | +| `readReplicas.service.loadBalancerSourceRanges` | Addresses that are allowed when service is LoadBalancer | `[]` | +| `readReplicas.service.extraPorts` | Extra ports to expose in the PostgreSQL read only service | `[]` | +| `readReplicas.service.sessionAffinity` | Session Affinity for Kubernetes service, can be "None" or "ClientIP" | `None` | +| `readReplicas.service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `readReplicas.persistence.enabled` | Enable PostgreSQL read only data persistence using PVC | `true` | +| `readReplicas.persistence.mountPath` | The path the volume will be mounted at | `/bitnami/postgresql` | +| `readReplicas.persistence.subPath` | The subdirectory of the volume to mount to | `""` | +| `readReplicas.persistence.storageClass` | PVC Storage Class for PostgreSQL read only data volume | `""` | +| `readReplicas.persistence.accessModes` | PVC Access Mode for PostgreSQL volume | `["ReadWriteOnce"]` | +| `readReplicas.persistence.size` | PVC Storage Request for PostgreSQL volume | `8Gi` | +| `readReplicas.persistence.annotations` | Annotations for the PVC | `{}` | +| `readReplicas.persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` | +| `readReplicas.persistence.dataSource` | Custom PVC data source | `{}` | + + +### NetworkPolicy parameters + +| Name | Description | Value | +| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `networkPolicy.enabled` | Enable network policies | `false` | +| `networkPolicy.metrics.enabled` | Enable network policies for metrics (prometheus) | `false` | +| `networkPolicy.metrics.namespaceSelector` | Monitoring namespace selector labels. These labels will be used to identify the prometheus' namespace. | `{}` | +| `networkPolicy.metrics.podSelector` | Monitoring pod selector labels. These labels will be used to identify the Prometheus pods. | `{}` | +| `networkPolicy.ingressRules.primaryAccessOnlyFrom.enabled` | Enable ingress rule that makes PostgreSQL primary node only accessible from a particular origin. | `false` | +| `networkPolicy.ingressRules.primaryAccessOnlyFrom.namespaceSelector` | Namespace selector label that is allowed to access the PostgreSQL primary node. This label will be used to identified the allowed namespace(s). | `{}` | +| `networkPolicy.ingressRules.primaryAccessOnlyFrom.podSelector` | Pods selector label that is allowed to access the PostgreSQL primary node. This label will be used to identified the allowed pod(s). | `{}` | +| `networkPolicy.ingressRules.primaryAccessOnlyFrom.customRules` | Custom network policy for the PostgreSQL primary node. | `{}` | +| `networkPolicy.ingressRules.readReplicasAccessOnlyFrom.enabled` | Enable ingress rule that makes PostgreSQL read-only nodes only accessible from a particular origin. | `false` | +| `networkPolicy.ingressRules.readReplicasAccessOnlyFrom.namespaceSelector` | Namespace selector label that is allowed to access the PostgreSQL read-only nodes. This label will be used to identified the allowed namespace(s). | `{}` | +| `networkPolicy.ingressRules.readReplicasAccessOnlyFrom.podSelector` | Pods selector label that is allowed to access the PostgreSQL read-only nodes. This label will be used to identified the allowed pod(s). | `{}` | +| `networkPolicy.ingressRules.readReplicasAccessOnlyFrom.customRules` | Custom network policy for the PostgreSQL read-only nodes. | `{}` | +| `networkPolicy.egressRules.denyConnectionsToExternal` | Enable egress rule that denies outgoing traffic outside the cluster, except for DNS (port 53). | `false` | +| `networkPolicy.egressRules.customRules` | Custom network policy rule | `{}` | + + +### Volume Permissions parameters + +| Name | Description | Value | +| ------------------------------------------------------ | ------------------------------------------------------------------------------- | ----------------------- | +| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | +| `volumePermissions.image.repository` | Init container volume-permissions image repository | `bitnami/bitnami-shell` | +| `volumePermissions.image.tag` | Init container volume-permissions image tag (immutable tags are recommended) | `11-debian-11-r9` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `IfNotPresent` | +| `volumePermissions.image.pullSecrets` | Init container volume-permissions image pull secrets | `[]` | +| `volumePermissions.resources.limits` | Init container volume-permissions resource limits | `{}` | +| `volumePermissions.resources.requests` | Init container volume-permissions resource requests | `{}` | +| `volumePermissions.containerSecurityContext.runAsUser` | User ID for the init container | `0` | + + +### Other Parameters + +| Name | Description | Value | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `serviceAccount.create` | Enable creation of ServiceAccount for PostgreSQL pod | `false` | +| `serviceAccount.name` | The name of the ServiceAccount to use. | `""` | +| `serviceAccount.automountServiceAccountToken` | Allows auto mount of ServiceAccountToken on the serviceAccount created | `true` | +| `serviceAccount.annotations` | Additional custom annotations for the ServiceAccount | `{}` | +| `rbac.create` | Create Role and RoleBinding (required for PSP to work) | `false` | +| `rbac.rules` | Custom RBAC rules to set | `[]` | +| `psp.create` | Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later | `false` | + + +### Metrics Parameters + +| Name | Description | Value | +| ----------------------------------------------- | ------------------------------------------------------------------------------------- | --------------------------- | +| `metrics.enabled` | Start a prometheus exporter | `false` | +| `metrics.image.registry` | PostgreSQL Prometheus Exporter image registry | `docker.io` | +| `metrics.image.repository` | PostgreSQL Prometheus Exporter image repository | `bitnami/postgres-exporter` | +| `metrics.image.tag` | PostgreSQL Prometheus Exporter image tag (immutable tags are recommended) | `0.10.1-debian-11-r9` | +| `metrics.image.pullPolicy` | PostgreSQL Prometheus Exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify image pull secrets | `[]` | +| `metrics.customMetrics` | Define additional custom metrics | `{}` | +| `metrics.extraEnvVars` | Extra environment variables to add to PostgreSQL Prometheus exporter | `[]` | +| `metrics.containerSecurityContext.enabled` | Enable PostgreSQL Prometheus exporter containers' Security Context | `true` | +| `metrics.containerSecurityContext.runAsUser` | Set PostgreSQL Prometheus exporter containers' Security Context runAsUser | `1001` | +| `metrics.containerSecurityContext.runAsNonRoot` | Set PostgreSQL Prometheus exporter containers' Security Context runAsNonRoot | `true` | +| `metrics.livenessProbe.enabled` | Enable livenessProbe on PostgreSQL Prometheus exporter containers | `true` | +| `metrics.livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `5` | +| `metrics.livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `metrics.livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `5` | +| `metrics.livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `6` | +| `metrics.livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `metrics.readinessProbe.enabled` | Enable readinessProbe on PostgreSQL Prometheus exporter containers | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `5` | +| `metrics.readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `metrics.readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `5` | +| `metrics.readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `6` | +| `metrics.readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `metrics.startupProbe.enabled` | Enable startupProbe on PostgreSQL Prometheus exporter containers | `false` | +| `metrics.startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `10` | +| `metrics.startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `metrics.startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` | +| `metrics.startupProbe.failureThreshold` | Failure threshold for startupProbe | `15` | +| `metrics.startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `metrics.customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `metrics.customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `metrics.customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `metrics.containerPorts.metrics` | PostgreSQL Prometheus exporter metrics container port | `9187` | +| `metrics.resources.limits` | The resources limits for the PostgreSQL Prometheus exporter container | `{}` | +| `metrics.resources.requests` | The requested resources for the PostgreSQL Prometheus exporter container | `{}` | +| `metrics.service.ports.metrics` | PostgreSQL Prometheus Exporter service port | `9187` | +| `metrics.service.clusterIP` | Static clusterIP or None for headless services | `""` | +| `metrics.service.sessionAffinity` | Control where client requests go, to the same pod or round-robin | `None` | +| `metrics.service.annotations` | Annotations for Prometheus to auto-discover the metrics endpoint | `{}` | +| `metrics.serviceMonitor.enabled` | Create ServiceMonitor Resource for scraping metrics using Prometheus Operator | `false` | +| `metrics.serviceMonitor.namespace` | Namespace for the ServiceMonitor Resource (defaults to the Release Namespace) | `""` | +| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. | `""` | +| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.labels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` | +| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `{}` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion | `[]` | +| `metrics.serviceMonitor.honorLabels` | Specify honorLabels parameter to add the scrape endpoint | `false` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `metrics.prometheusRule.enabled` | Create a PrometheusRule for Prometheus Operator | `false` | +| `metrics.prometheusRule.namespace` | Namespace for the PrometheusRule Resource (defaults to the Release Namespace) | `""` | +| `metrics.prometheusRule.labels` | Additional labels that can be used so PrometheusRule will be discovered by Prometheus | `{}` | +| `metrics.prometheusRule.rules` | PrometheusRule definitions | `[]` | + + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```bash +$ helm install my-release \ + --set auth.postgresPassword=secretpassword + bitnami/postgresql +``` + +The above command sets the PostgreSQL `postgres` account password to `secretpassword`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```bash +helm install my-release -f values.yaml bitnami/postgresql +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Configuration and installation details + +### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) + +It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. + +Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. + +### Customizing primary and read replica services in a replicated configuration + +At the top level, there is a service object which defines the services for both primary and readReplicas. For deeper customization, there are service objects for both the primary and read types individually. This allows you to override the values in the top level service object so that the primary and read can be of different service types and with different clusterIPs / nodePorts. Also in the case you want the primary and read to be of type nodePort, you will need to set the nodePorts to different values to prevent a collision. The values that are deeper in the primary.service or readReplicas.service objects will take precedence over the top level service object. + +### Use a different PostgreSQL version + +To modify the application version used in this chart, specify a different version of the image using the `image.tag` parameter and/or a different repository using the `image.repository` parameter. Refer to the [chart documentation for more information on these parameters and how to use them with images from a private registry](https://docs.bitnami.com/kubernetes/infrastructure/postgresql/configuration/change-image-version/). + +### postgresql.conf / pg_hba.conf files as configMap + +This helm chart also supports to customize the PostgreSQL configuration file. You can add additional PostgreSQL configuration parameters using the `primary.extendedConfiguration` parameter as a string. Alternatively, to replace the entire default configuration use `primary.configuration`. + +You can also add a custom pg_hba.conf using the `primary.pgHbaConfiguration` parameter. + +In addition to these options, you can also set an external ConfigMap with all the configuration files. This is done by setting the `primary.existingConfigmap` parameter. Note that this will override the two previous options. + +### Initialize a fresh instance + +The [Bitnami PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) image allows you to use your custom scripts to initialize a fresh instance. In order to execute the scripts, you can specify custom scripts using the `primary.initdb.scripts` parameter as a string. + +In addition, you can also set an external ConfigMap with all the initialization scripts. This is done by setting the `primary.initdb.scriptsConfigMap` parameter. Note that this will override the two previous options. If your initialization scripts contain sensitive information such as credentials or passwords, you can use the `primary.initdb.scriptsSecret` parameter. + +The allowed extensions are `.sh`, `.sql` and `.sql.gz`. + +### Securing traffic using TLS + +TLS support can be enabled in the chart by specifying the `tls.` parameters while creating a release. The following parameters should be configured to properly enable the TLS support in the chart: + +- `tls.enabled`: Enable TLS support. Defaults to `false` +- `tls.certificatesSecret`: Name of an existing secret that contains the certificates. No defaults. +- `tls.certFilename`: Certificate filename. No defaults. +- `tls.certKeyFilename`: Certificate key filename. No defaults. + +For example: + +- First, create the secret with the cetificates files: + + ```console + kubectl create secret generic certificates-tls-secret --from-file=./cert.crt --from-file=./cert.key --from-file=./ca.crt + ``` + +- Then, use the following parameters: + + ```console + volumePermissions.enabled=true + tls.enabled=true + tls.certificatesSecret="certificates-tls-secret" + tls.certFilename="cert.crt" + tls.certKeyFilename="cert.key" + ``` + + > Note TLS and VolumePermissions: PostgreSQL requires certain permissions on sensitive files (such as certificate keys) to start up. Due to an on-going [issue](https://github.com/kubernetes/kubernetes/issues/57923) regarding kubernetes permissions and the use of `containerSecurityContext.runAsUser`, you must enable `volumePermissions` to ensure everything works as expected. + +### Sidecars + +If you need additional containers to run within the same pod as PostgreSQL (e.g. an additional metrics or logging exporter), you can do so via the `sidecars` config parameter. Simply define your container according to the Kubernetes container spec. + +```yaml +# For the PostgreSQL primary +primary: + sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +# For the PostgreSQL replicas +readReplicas: + sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +### Metrics + +The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). The metrics endpoint (port 9187) is not exposed and it is expected that the metrics are collected from inside the k8s cluster using something similar as the described in the [example Prometheus scrape configuration](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml). + +The exporter allows to create custom metrics from additional SQL queries. See the Chart's `values.yaml` for an example and consult the [exporters documentation](https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file) for more details. + +### Use of global variables + +In more complex scenarios, we may have the following tree of dependencies + +``` + +--------------+ + | | + +------------+ Chart 1 +-----------+ + | | | | + | --------+------+ | + | | | + | | | + | | | + | | | + v v v ++-------+------+ +--------+------+ +--------+------+ +| | | | | | +| PostgreSQL | | Sub-chart 1 | | Sub-chart 2 | +| | | | | | ++--------------+ +---------------+ +---------------+ +``` + +The three charts below depend on the parent chart Chart 1. However, subcharts 1 and 2 may need to connect to PostgreSQL as well. In order to do so, subcharts 1 and 2 need to know the PostgreSQL credentials, so one option for deploying could be deploy Chart 1 with the following parameters: + +``` +postgresql.auth.username=testuser +subchart1.postgresql.auth.username=testuser +subchart2.postgresql.auth.username=testuser +postgresql.auth.password=testpass +subchart1.postgresql.auth.password=testpass +subchart2.postgresql.auth.password=testpass +postgresql.auth.database=testdb +subchart1.postgresql.auth.database=testdb +subchart2.postgresql.auth.database=testdb +``` + +If the number of dependent sub-charts increases, installing the chart with parameters can become increasingly difficult. An alternative would be to set the credentials using global variables as follows: + +``` +global.postgresql.auth.username=testuser +global.postgresql.auth.password=testpass +global.postgresql.auth.database=testdb +``` + +This way, the credentials will be available in all of the subcharts. + +## Persistence + +The [Bitnami PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) image stores the PostgreSQL data and configurations at the `/bitnami/postgresql` path of the container. + +Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube. +See the [Parameters](#parameters) section to configure the PVC or to disable persistence. + +If you already have data in it, you will fail to sync to standby nodes for all commits, details can refer to [code](https://github.com/bitnami/bitnami-docker-postgresql/blob/8725fe1d7d30ebe8d9a16e9175d05f7ad9260c93/9.6/debian-9/rootfs/libpostgresql.sh#L518-L556). If you need to use those data, please covert them to sql and import after `helm install` finished. + +## NetworkPolicy + +To enable network policy for PostgreSQL, install [a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin), and set `networkPolicy.enabled` to `true`. + +For Kubernetes v1.5 & v1.6, you must also turn on NetworkPolicy by setting the DefaultDeny namespace annotation. Note: this will enforce policy for _all_ pods in the namespace: + +```bash +kubectl annotate namespace default "net.beta.kubernetes.io/network-policy={\"ingress\":{\"isolation\":\"DefaultDeny\"}}" +``` + +With NetworkPolicy enabled, traffic will be limited to just port 5432. + +For more precise policy, set `networkPolicy.allowExternal=false`. This will only allow pods with the generated client label to connect to PostgreSQL. +This label will be displayed in the output of a successful install. + +## Differences between Bitnami PostgreSQL image and [Docker Official](https://hub.docker.com/_/postgres) image + +- The Docker Official PostgreSQL image does not support replication. If you pass any replication environment variable, this would be ignored. The only environment variables supported by the Docker Official image are POSTGRES_USER, POSTGRES_DB, POSTGRES_PASSWORD, POSTGRES_INITDB_ARGS, POSTGRES_INITDB_WALDIR and PGDATA. All the remaining environment variables are specific to the Bitnami PostgreSQL image. +- The Bitnami PostgreSQL image is non-root by default. This requires that you run the pod with `securityContext` and updates the permissions of the volume with an `initContainer`. A key benefit of this configuration is that the pod follows security best practices and is prepared to run on Kubernetes distributions with hard security constraints like OpenShift. +- For OpenShift, one may either define the runAsUser and fsGroup accordingly, or try this more dynamic option: volumePermissions.securityContext.runAsUser="auto",securityContext.enabled=false,containerSecurityContext.enabled=false,shmVolume.chmod.enabled=false + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` parameter(s). Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/master/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami's Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +Refer to the [chart documentation for more information about how to upgrade from previous releases](https://docs.bitnami.com/kubernetes/infrastructure/postgresql/administration/upgrade/). + +## License + +Copyright © 2022 Bitnami + +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. \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/.helmignore b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/.helmignore new file mode 100644 index 00000000..50af0317 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/Chart.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/Chart.yaml new file mode 100644 index 00000000..bd152e31 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + category: Infrastructure +apiVersion: v2 +appVersion: 1.16.0 +description: A Library Helm Chart for grouping common logic between bitnami charts. + This chart is not deployable by itself. +home: https://github.com/bitnami/charts/tree/master/bitnami/common +icon: https://bitnami.com/downloads/logos/bitnami-mark.png +keywords: +- common +- helper +- template +- function +- bitnami +maintainers: +- name: Bitnami + url: https://github.com/bitnami/charts +name: common +sources: +- https://github.com/bitnami/charts +- https://www.bitnami.com/ +type: library +version: 1.16.0 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/README.md b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/README.md new file mode 100644 index 00000000..3b5e09c5 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/README.md @@ -0,0 +1,350 @@ +# Bitnami Common Library Chart + +A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between bitnami charts. + +## TL;DR + +```yaml +dependencies: + - name: common + version: 1.x.x + repository: https://charts.bitnami.com/bitnami +``` + +```bash +$ helm dependency update +``` + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }} +data: + myvalue: "Hello World" +``` + +## Introduction + +This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This Helm chart has been tested on top of [Bitnami Kubernetes Production Runtime](https://kubeprod.io/) (BKPR). Deploy BKPR to get automated TLS certificates, logging and monitoring for your applications. + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.2.0+ + +## Parameters + +The following table lists the helpers available in the library which are scoped in different sections. + +### Affinities + +| Helper identifier | Description | Expected Input | +|-------------------------------|------------------------------------------------------|------------------------------------------------| +| `common.affinities.nodes.soft` | Return a soft nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.nodes.hard` | Return a hard nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | +| `common.affinities.pods.soft` | Return a soft podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | +| `common.affinities.pods.hard` | Return a hard podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | + +### Capabilities + +| Helper identifier | Description | Expected Input | +|------------------------------------------------|------------------------------------------------------------------------------------------------|-------------------| +| `common.capabilities.kubeVersion` | Return the target Kubernetes version (using client default if .Values.kubeVersion is not set). | `.` Chart context | +| `common.capabilities.cronjob.apiVersion` | Return the appropriate apiVersion for cronjob. | `.` Chart context | +| `common.capabilities.deployment.apiVersion` | Return the appropriate apiVersion for deployment. | `.` Chart context | +| `common.capabilities.statefulset.apiVersion` | Return the appropriate apiVersion for statefulset. | `.` Chart context | +| `common.capabilities.ingress.apiVersion` | Return the appropriate apiVersion for ingress. | `.` Chart context | +| `common.capabilities.rbac.apiVersion` | Return the appropriate apiVersion for RBAC resources. | `.` Chart context | +| `common.capabilities.crd.apiVersion` | Return the appropriate apiVersion for CRDs. | `.` Chart context | +| `common.capabilities.policy.apiVersion` | Return the appropriate apiVersion for podsecuritypolicy. | `.` Chart context | +| `common.capabilities.networkPolicy.apiVersion` | Return the appropriate apiVersion for networkpolicy. | `.` Chart context | +| `common.capabilities.apiService.apiVersion` | Return the appropriate apiVersion for APIService. | `.` Chart context | +| `common.capabilities.hpa.apiVersion` | Return the appropriate apiVersion for Horizontal Pod Autoscaler | `.` Chart context | +| `common.capabilities.supportsHelmVersion` | Returns true if the used Helm version is 3.3+ | `.` Chart context | + +### Errors + +| Helper identifier | Description | Expected Input | +|-----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------| +| `common.errors.upgrade.passwords.empty` | It will ensure required passwords are given when we are upgrading a chart. If `validationErrors` is not empty it will throw an error and will stop the upgrade action. | `dict "validationErrors" (list $validationError00 $validationError01) "context" $` | + +### Images + +| Helper identifier | Description | Expected Input | +|-----------------------------|------------------------------------------------------|---------------------------------------------------------------------------------------------------------| +| `common.images.image` | Return the proper and full image name | `dict "imageRoot" .Values.path.to.the.image "global" $`, see [ImageRoot](#imageroot) for the structure. | +| `common.images.pullSecrets` | Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global` | +| `common.images.renderPullSecrets` | Return the proper Docker Image Registry Secret Names (evaluates values as templates) | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $` | + +### Ingress + +| Helper identifier | Description | Expected Input | +|-------------------------------------------|-------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `common.ingress.backend` | Generate a proper Ingress backend entry depending on the API version | `dict "serviceName" "foo" "servicePort" "bar"`, see the [Ingress deprecation notice](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/) for the syntax differences | +| `common.ingress.supportsPathType` | Prints "true" if the pathType field is supported | `.` Chart context | +| `common.ingress.supportsIngressClassname` | Prints "true" if the ingressClassname field is supported | `.` Chart context | +| `common.ingress.certManagerRequest` | Prints "true" if required cert-manager annotations for TLS signed certificates are set in the Ingress annotations | `dict "annotations" .Values.path.to.the.ingress.annotations` | + +### Labels + +| Helper identifier | Description | Expected Input | +|-----------------------------|-----------------------------------------------------------------------------|-------------------| +| `common.labels.standard` | Return Kubernetes standard labels | `.` Chart context | +| `common.labels.matchLabels` | Labels to use on `deploy.spec.selector.matchLabels` and `svc.spec.selector` | `.` Chart context | + +### Names + +| Helper identifier | Description | Expected Input | +|-----------------------------------|-----------------------------------------------------------------------|-------------------| +| `common.names.name` | Expand the name of the chart or use `.Values.nameOverride` | `.` Chart context | +| `common.names.fullname` | Create a default fully qualified app name. | `.` Chart context | +| `common.names.namespace` | Allow the release namespace to be overridden | `.` Chart context | +| `common.names.fullname.namespace` | Create a fully qualified app name adding the installation's namespace | `.` Chart context | +| `common.names.chart` | Chart name plus version | `.` Chart context | + +### Secrets + +| Helper identifier | Description | Expected Input | +|---------------------------|--------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `common.secrets.name` | Generate the name of the secret. | `dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $` see [ExistingSecret](#existingsecret) for the structure. | +| `common.secrets.key` | Generate secret key. | `dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName"` see [ExistingSecret](#existingsecret) for the structure. | +| `common.passwords.manage` | Generate secret password or retrieve one if already created. | `dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $`, length, strong and chartNAme fields are optional. | +| `common.secrets.exists` | Returns whether a previous generated secret already exists. | `dict "secret" "secret-name" "context" $` | + +### Storage + +| Helper identifier | Description | Expected Input | +|-------------------------------|---------------------------------------|---------------------------------------------------------------------------------------------------------------------| +| `common.storage.class` | Return the proper Storage Class | `dict "persistence" .Values.path.to.the.persistence "global" $`, see [Persistence](#persistence) for the structure. | + +### TplValues + +| Helper identifier | Description | Expected Input | +|---------------------------|----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| +| `common.tplvalues.render` | Renders a value that contains template | `dict "value" .Values.path.to.the.Value "context" $`, value is the value should rendered as template, context frequently is the chart context `$` or `.` | + +### Utils + +| Helper identifier | Description | Expected Input | +|--------------------------------|------------------------------------------------------------------------------------------|------------------------------------------------------------------------| +| `common.utils.fieldToEnvVar` | Build environment variable name given a field. | `dict "field" "my-password"` | +| `common.utils.secret.getvalue` | Print instructions to get a secret value. | `dict "secret" "secret-name" "field" "secret-value-field" "context" $` | +| `common.utils.getValueFromKey` | Gets a value from `.Values` object given its key path | `dict "key" "path.to.key" "context" $` | +| `common.utils.getKeyFromList` | Returns first `.Values` key with a defined value or first of the list if all non-defined | `dict "keys" (list "path.to.key1" "path.to.key2") "context" $` | + +### Validations + +| Helper identifier | Description | Expected Input | +|--------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `common.validations.values.single.empty` | Validate a value must not be empty. | `dict "valueKey" "path.to.value" "secret" "secret.name" "field" "my-password" "subchart" "subchart" "context" $` secret, field and subchart are optional. In case they are given, the helper will generate a how to get instruction. See [ValidateValue](#validatevalue) | +| `common.validations.values.multiple.empty` | Validate a multiple values must not be empty. It returns a shared error for all the values. | `dict "required" (list $validateValueConf00 $validateValueConf01) "context" $`. See [ValidateValue](#validatevalue) | +| `common.validations.values.mariadb.passwords` | This helper will ensure required password for MariaDB are not empty. It returns a shared error for all the values. | `dict "secret" "mariadb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mariadb chart and the helper. | +| `common.validations.values.mysql.passwords` | This helper will ensure required password for MySQL are not empty. It returns a shared error for all the values. | `dict "secret" "mysql-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mysql chart and the helper. | +| `common.validations.values.postgresql.passwords` | This helper will ensure required password for PostgreSQL are not empty. It returns a shared error for all the values. | `dict "secret" "postgresql-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use postgresql chart and the helper. | +| `common.validations.values.redis.passwords` | This helper will ensure required password for Redis® are not empty. It returns a shared error for all the values. | `dict "secret" "redis-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use redis chart and the helper. | +| `common.validations.values.cassandra.passwords` | This helper will ensure required password for Cassandra are not empty. It returns a shared error for all the values. | `dict "secret" "cassandra-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use cassandra chart and the helper. | +| `common.validations.values.mongodb.passwords` | This helper will ensure required password for MongoDB® are not empty. It returns a shared error for all the values. | `dict "secret" "mongodb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mongodb chart and the helper. | + +### Warnings + +| Helper identifier | Description | Expected Input | +|------------------------------|----------------------------------|------------------------------------------------------------| +| `common.warnings.rollingTag` | Warning about using rolling tag. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | + +## Special input schemas + +### ImageRoot + +```yaml +registry: + type: string + description: Docker registry where the image is located + example: docker.io + +repository: + type: string + description: Repository and image name + example: bitnami/nginx + +tag: + type: string + description: image tag + example: 1.16.1-debian-10-r63 + +pullPolicy: + type: string + description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + +pullSecrets: + type: array + items: + type: string + description: Optionally specify an array of imagePullSecrets (evaluated as templates). + +debug: + type: boolean + description: Set to true if you would like to see extra information on logs + example: false + +## An instance would be: +# registry: docker.io +# repository: bitnami/nginx +# tag: 1.16.1-debian-10-r63 +# pullPolicy: IfNotPresent +# debug: false +``` + +### Persistence + +```yaml +enabled: + type: boolean + description: Whether enable persistence. + example: true + +storageClass: + type: string + description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. + example: "-" + +accessMode: + type: string + description: Access mode for the Persistent Volume Storage. + example: ReadWriteOnce + +size: + type: string + description: Size the Persistent Volume Storage. + example: 8Gi + +path: + type: string + description: Path to be persisted. + example: /bitnami + +## An instance would be: +# enabled: true +# storageClass: "-" +# accessMode: ReadWriteOnce +# size: 8Gi +# path: /bitnami +``` + +### ExistingSecret + +```yaml +name: + type: string + description: Name of the existing secret. + example: mySecret +keyMapping: + description: Mapping between the expected key name and the name of the key in the existing secret. + type: object + +## An instance would be: +# name: mySecret +# keyMapping: +# password: myPasswordKey +``` + +#### Example of use + +When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. + +```yaml +# templates/secret.yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + app: {{ include "common.names.fullname" . }} +type: Opaque +data: + password: {{ .Values.password | b64enc | quote }} + +# templates/dpl.yaml +--- +... + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} + key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} +... + +# values.yaml +--- +name: mySecret +keyMapping: + password: myPasswordKey +``` + +### ValidateValue + +#### NOTES.txt + +```console +{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} + +{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} +``` + +If we force those values to be empty we will see some alerts + +```console +$ helm install test mychart --set path.to.value00="",path.to.value01="" + 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: + + export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 -d) + + 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: + + export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 -d) +``` + +## Upgrading + +### To 1.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +**What changes were introduced in this major version?** + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts + +**Considerations when upgrading to this version** + +- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +**Useful links** + +- https://docs.bitnami.com/tutorials/resolve-helm2-helm3-post-migration-issues/ +- https://helm.sh/docs/topics/v2_v3_migration/ +- https://helm.sh/blog/migrate-from-helm-v2-to-helm-v3/ + +## License + +Copyright © 2022 Bitnami + +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. diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_affinities.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_affinities.tpl new file mode 100644 index 00000000..189ea403 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_affinities.tpl @@ -0,0 +1,102 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . | quote }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "extraMatchLabels" .Values.extraMatchLabels "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" .context) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + namespaces: + - {{ .context.Release.Namespace | quote }} + topologyKey: kubernetes.io/hostname + weight: 1 +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "extraMatchLabels" .Values.extraMatchLabels "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +{{- $extraMatchLabels := default (dict) .extraMatchLabels -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" .context) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + {{- range $key, $value := $extraMatchLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + namespaces: + - {{ .context.Release.Namespace | quote }} + topologyKey: kubernetes.io/hostname +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_capabilities.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_capabilities.tpl new file mode 100644 index 00000000..9d9b7600 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_capabilities.tpl @@ -0,0 +1,154 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- if .Values.global }} + {{- if .Values.global.kubeVersion }} + {{- .Values.global.kubeVersion -}} + {{- else }} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} + {{- end -}} +{{- else }} +{{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "common.capabilities.policy.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "common.capabilities.networkPolicy.apiVersion" -}} +{{- if semverCompare "<1.7-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for cronjob. +*/}} +{{- define "common.capabilities.cronjob.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "batch/v1beta1" -}} +{{- else -}} +{{- print "batch/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- if .Values.ingress -}} +{{- if .Values.ingress.apiVersion -}} +{{- .Values.ingress.apiVersion -}} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end }} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- if semverCompare "<1.17-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiextensions.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for APIService. +*/}} +{{- define "common.capabilities.apiService.apiVersion" -}} +{{- if semverCompare "<1.10-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiregistration.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiregistration.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "common.capabilities.hpa.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "common.capabilities.kubeVersion" .context) -}} +{{- if .beta2 -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2beta1" -}} +{{- end -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_errors.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_errors.tpl new file mode 100644 index 00000000..a79cc2e3 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_errors.tpl @@ -0,0 +1,23 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Through error when upgrading using empty passwords values that must not be empty. + +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} + {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} + {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} + {{- $errorString = print $errorString "\n%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_images.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_images.tpl new file mode 100644 index 00000000..42ffbc72 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_images.tpl @@ -0,0 +1,75 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper image name +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" $) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := .imageRoot.registry -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $tag := .imageRoot.tag | toString -}} +{{- if .global }} + {{- if .global.imageRegistry }} + {{- $registryName = .global.imageRegistry -}} + {{- end -}} +{{- end -}} +{{- if $registryName }} +{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- else -}} +{{- printf "%s:%s" $repositoryName $tag -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names (deprecated: use common.images.renderPullSecrets instead) +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- if .global }} + {{- range .global.imagePullSecrets -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names evaluating values as templates +{{ include "common.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }} +*/}} +{{- define "common.images.renderPullSecrets" -}} + {{- $pullSecrets := list }} + {{- $context := .context }} + + {{- if $context.Values.global }} + {{- range $context.Values.global.imagePullSecrets -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- $pullSecrets = append $pullSecrets (include "common.tplvalues.render" (dict "value" . "context" $context)) -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_ingress.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_ingress.tpl new file mode 100644 index 00000000..8caf73a6 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_ingress.tpl @@ -0,0 +1,68 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Generate backend entry that is compatible with all Kubernetes API versions. + +Usage: +{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} + +Params: + - serviceName - String. Name of an existing service backend + - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.ingress.backend" -}} +{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}} +{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}} +serviceName: {{ .serviceName }} +servicePort: {{ .servicePort }} +{{- else -}} +service: + name: {{ .serviceName }} + port: + {{- if typeIs "string" .servicePort }} + name: {{ .servicePort }} + {{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }} + number: {{ .servicePort | int }} + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +Print "true" if the API pathType field is supported +Usage: +{{ include "common.ingress.supportsPathType" . }} +*/}} +{{- define "common.ingress.supportsPathType" -}} +{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the ingressClassname field is supported +Usage: +{{ include "common.ingress.supportsIngressClassname" . }} +*/}} +{{- define "common.ingress.supportsIngressClassname" -}} +{{- if semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "false" -}} +{{- else -}} +{{- print "true" -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if cert-manager required annotations for TLS signed +certificates are set in the Ingress annotations +Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations +Usage: +{{ include "common.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }} +*/}} +{{- define "common.ingress.certManagerRequest" -}} +{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_labels.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_labels.tpl new file mode 100644 index 00000000..252066c7 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_labels.tpl @@ -0,0 +1,18 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Kubernetes standard labels +*/}} +{{- define "common.labels.standard" -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector +*/}} +{{- define "common.labels.matchLabels" -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_names.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_names.tpl new file mode 100644 index 00000000..1bdac8b7 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_names.tpl @@ -0,0 +1,70 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "common.names.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified dependency name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +Usage: +{{ include "common.names.dependency.fullname" (dict "chartName" "dependency-chart-name" "chartValues" .Values.dependency-chart "context" $) }} +*/}} +{{- define "common.names.dependency.fullname" -}} +{{- if .chartValues.fullnameOverride -}} +{{- .chartValues.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .chartName .chartValues.nameOverride -}} +{{- if contains $name .context.Release.Name -}} +{{- .context.Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .context.Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "common.names.namespace" -}} +{{- if .Values.namespaceOverride -}} +{{- .Values.namespaceOverride -}} +{{- else -}} +{{- .Release.Namespace -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified app name adding the installation's namespace. +*/}} +{{- define "common.names.fullname.namespace" -}} +{{- printf "%s-%s" (include "common.names.fullname" .) (include "common.names.namespace" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_secrets.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_secrets.tpl new file mode 100644 index 00000000..a53fb44f --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_secrets.tpl @@ -0,0 +1,140 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Generate secret name. + +Usage: +{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/master/bitnami/common#existingsecret + - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. + - context - Dict - Required. The context for the template evaluation. +*/}} +{{- define "common.secrets.name" -}} +{{- $name := (include "common.names.fullname" .context) -}} + +{{- if .defaultNameSuffix -}} +{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- with .existingSecret -}} +{{- if not (typeIs "string" .) -}} +{{- with .name -}} +{{- $name = . -}} +{{- end -}} +{{- else -}} +{{- $name = . -}} +{{- end -}} +{{- end -}} + +{{- printf "%s" $name -}} +{{- end -}} + +{{/* +Generate secret key. + +Usage: +{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} + +Params: + - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user + to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. + +info: https://github.com/bitnami/charts/tree/master/bitnami/common#existingsecret + - key - String - Required. Name of the key in the secret. +*/}} +{{- define "common.secrets.key" -}} +{{- $key := .key -}} + +{{- if .existingSecret -}} + {{- if not (typeIs "string" .existingSecret) -}} + {{- if .existingSecret.keyMapping -}} + {{- $key = index .existingSecret.keyMapping $.key -}} + {{- end -}} + {{- end }} +{{- end -}} + +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Generate secret password or retrieve one if already created. + +Usage: +{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - key - String - Required - Name of the key in the secret. + - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. + - length - int - Optional - Length of the generated random password. + - strong - Boolean - Optional - Whether to add symbols to the generated random password. + - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. + - context - Context - Required - Parent context. + +The order in which this function returns a secret password: + 1. Already existing 'Secret' resource + (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) + 2. Password provided via the values.yaml + (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) + 3. Randomly generated secret password + (A new random secret password with the length specified in the 'length' parameter will be generated and returned) + +*/}} +{{- define "common.secrets.passwords.manage" -}} + +{{- $password := "" }} +{{- $subchart := "" }} +{{- $chartName := default "" .chartName }} +{{- $passwordLength := default 10 .length }} +{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} +{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} +{{- $secretData := (lookup "v1" "Secret" $.context.Release.Namespace .secret).data }} +{{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $password = index $secretData .key }} + {{- else }} + {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} + {{- end -}} +{{- else if $providedPasswordValue }} + {{- $password = $providedPasswordValue | toString | b64enc | quote }} +{{- else }} + + {{- if .context.Values.enabled }} + {{- $subchart = $chartName }} + {{- end -}} + + {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} + {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} + {{- $passwordValidationErrors := list $requiredPasswordError -}} + {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} + + {{- if .strong }} + {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} + {{- $password = randAscii $passwordLength }} + {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} + {{- $password = printf "%s%s" $subStr $password | toString | shuffle | b64enc | quote }} + {{- else }} + {{- $password = randAlphaNum $passwordLength | b64enc | quote }} + {{- end }} +{{- end -}} +{{- printf "%s" $password -}} +{{- end -}} + +{{/* +Returns whether a previous generated secret already exists + +Usage: +{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} + +Params: + - secret - String - Required - Name of the 'Secret' resource where the password is stored. + - context - Context - Required - Parent context. +*/}} +{{- define "common.secrets.exists" -}} +{{- $secret := (lookup "v1" "Secret" $.context.Release.Namespace .secret) }} +{{- if $secret }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_storage.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_storage.tpl new file mode 100644 index 00000000..60e2a844 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_storage.tpl @@ -0,0 +1,23 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} + +{{- $storageClass := .persistence.storageClass -}} +{{- if .global -}} + {{- if .global.storageClass -}} + {{- $storageClass = .global.storageClass -}} + {{- end -}} +{{- end -}} + +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else }} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} + +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_tplvalues.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_tplvalues.tpl new file mode 100644 index 00000000..2db16685 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_tplvalues.tpl @@ -0,0 +1,13 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Renders a value that contains template. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $) }} +*/}} +{{- define "common.tplvalues.render" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{- else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_utils.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_utils.tpl new file mode 100644 index 00000000..8c22b2a3 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_utils.tpl @@ -0,0 +1,62 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ .context.Release.Namespace | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_warnings.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_warnings.tpl new file mode 100644 index 00000000..ae10fa41 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_warnings.tpl @@ -0,0 +1,14 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ +{{- end }} + +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_cassandra.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_cassandra.tpl new file mode 100644 index 00000000..ded1ae3b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_cassandra.tpl @@ -0,0 +1,72 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Cassandra required passwords are not empty. + +Usage: +{{ include "common.validations.values.cassandra.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where Cassandra values are stored, e.g: "cassandra-passwords-secret" + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.cassandra.passwords" -}} + {{- $existingSecret := include "common.cassandra.values.existingSecret" . -}} + {{- $enabled := include "common.cassandra.values.enabled" . -}} + {{- $dbUserPrefix := include "common.cassandra.values.key.dbUser" . -}} + {{- $valueKeyPassword := printf "%s.password" $dbUserPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "cassandra-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.dbUser.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled cassandra. + +Usage: +{{ include "common.cassandra.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.cassandra.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.cassandra.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key dbUser + +Usage: +{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false +*/}} +{{- define "common.cassandra.values.key.dbUser" -}} + {{- if .subchart -}} + cassandra.dbUser + {{- else -}} + dbUser + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mariadb.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mariadb.tpl new file mode 100644 index 00000000..b6906ff7 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mariadb.tpl @@ -0,0 +1,103 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MariaDB required passwords are not empty. + +Usage: +{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mariadb.passwords" -}} + {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mariadb.values.enabled" . -}} + {{- $architecture := include "common.mariadb.values.architecture" . -}} + {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mariadb. + +Usage: +{{ include "common.mariadb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mariadb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mariadb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mariadb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false +*/}} +{{- define "common.mariadb.values.key.auth" -}} + {{- if .subchart -}} + mariadb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mongodb.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mongodb.tpl new file mode 100644 index 00000000..f820ec10 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mongodb.tpl @@ -0,0 +1,108 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MongoDB® required passwords are not empty. + +Usage: +{{ include "common.validations.values.mongodb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MongoDB® values are stored, e.g: "mongodb-passwords-secret" + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mongodb.passwords" -}} + {{- $existingSecret := include "common.mongodb.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mongodb.values.enabled" . -}} + {{- $authPrefix := include "common.mongodb.values.key.auth" . -}} + {{- $architecture := include "common.mongodb.values.architecture" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyDatabase := printf "%s.database" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicaSetKey := printf "%s.replicaSetKey" $authPrefix -}} + {{- $valueKeyAuthEnabled := printf "%s.enabled" $authPrefix -}} + + {{- $authEnabled := include "common.utils.getValueFromKey" (dict "key" $valueKeyAuthEnabled "context" .context) -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") (eq $authEnabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mongodb-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- $valueDatabase := include "common.utils.getValueFromKey" (dict "key" $valueKeyDatabase "context" .context) }} + {{- if and $valueUsername $valueDatabase -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mongodb-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replicaset") -}} + {{- $requiredReplicaSetKey := dict "valueKey" $valueKeyReplicaSetKey "secret" .secret "field" "mongodb-replica-set-key" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicaSetKey -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mongodb. + +Usage: +{{ include "common.mongodb.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mongodb.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mongodb.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.key.auth" -}} + {{- if .subchart -}} + mongodb.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MongoDB® is used as subchart or not. Default: false +*/}} +{{- define "common.mongodb.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mongodb.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mysql.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mysql.tpl new file mode 100644 index 00000000..74472a06 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mysql.tpl @@ -0,0 +1,103 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Validate MySQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.mysql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where MySQL values are stored, e.g: "mysql-passwords-secret" + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.mysql.passwords" -}} + {{- $existingSecret := include "common.mysql.values.auth.existingSecret" . -}} + {{- $enabled := include "common.mysql.values.enabled" . -}} + {{- $architecture := include "common.mysql.values.architecture" . -}} + {{- $authPrefix := include "common.mysql.values.key.auth" . -}} + {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} + {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} + {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} + {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mysql-root-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} + + {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} + {{- if not (empty $valueUsername) -}} + {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mysql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} + {{- end -}} + + {{- if (eq $architecture "replication") -}} + {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mysql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.mysql.values.auth.existingSecret" (dict "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.auth.existingSecret" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.auth.existingSecret | quote -}} + {{- else -}} + {{- .context.Values.auth.existingSecret | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled mysql. + +Usage: +{{ include "common.mysql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.mysql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.mysql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for architecture + +Usage: +{{ include "common.mysql.values.architecture" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.architecture" -}} + {{- if .subchart -}} + {{- .context.Values.mysql.architecture -}} + {{- else -}} + {{- .context.Values.architecture -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key auth + +Usage: +{{ include "common.mysql.values.key.auth" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether MySQL is used as subchart or not. Default: false +*/}} +{{- define "common.mysql.values.key.auth" -}} + {{- if .subchart -}} + mysql.auth + {{- else -}} + auth + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_postgresql.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_postgresql.tpl new file mode 100644 index 00000000..164ec0d0 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_postgresql.tpl @@ -0,0 +1,129 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Validate PostgreSQL required passwords are not empty. + +Usage: +{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where postgresql values are stored, e.g: "postgresql-passwords-secret" + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.postgresql.passwords" -}} + {{- $existingSecret := include "common.postgresql.values.existingSecret" . -}} + {{- $enabled := include "common.postgresql.values.enabled" . -}} + {{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}} + {{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}} + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + {{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}} + + {{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}} + {{- if (eq $enabledReplication "true") -}} + {{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to decide whether evaluate global values. + +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. + +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. + +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. + +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. + +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. + +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_redis.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_redis.tpl new file mode 100644 index 00000000..dcccfc1a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_redis.tpl @@ -0,0 +1,76 @@ + +{{/* vim: set filetype=mustache: */}} +{{/* +Validate Redis® required passwords are not empty. + +Usage: +{{ include "common.validations.values.redis.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where redis values are stored, e.g: "redis-passwords-secret" + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.redis.passwords" -}} + {{- $enabled := include "common.redis.values.enabled" . -}} + {{- $valueKeyPrefix := include "common.redis.values.keys.prefix" . -}} + {{- $standarizedVersion := include "common.redis.values.standarized.version" . }} + + {{- $existingSecret := ternary (printf "%s%s" $valueKeyPrefix "auth.existingSecret") (printf "%s%s" $valueKeyPrefix "existingSecret") (eq $standarizedVersion "true") }} + {{- $existingSecretValue := include "common.utils.getValueFromKey" (dict "key" $existingSecret "context" .context) }} + + {{- $valueKeyRedisPassword := ternary (printf "%s%s" $valueKeyPrefix "auth.password") (printf "%s%s" $valueKeyPrefix "password") (eq $standarizedVersion "true") }} + {{- $valueKeyRedisUseAuth := ternary (printf "%s%s" $valueKeyPrefix "auth.enabled") (printf "%s%s" $valueKeyPrefix "usePassword") (eq $standarizedVersion "true") }} + + {{- if and (or (not $existingSecret) (eq $existingSecret "\"\"")) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $useAuth := include "common.utils.getValueFromKey" (dict "key" $valueKeyRedisUseAuth "context" .context) -}} + {{- if eq $useAuth "true" -}} + {{- $requiredRedisPassword := dict "valueKey" $valueKeyRedisPassword "secret" .secret "field" "redis-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredRedisPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled redis. + +Usage: +{{ include "common.redis.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.redis.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.redis.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right prefix path for the values + +Usage: +{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false +*/}} +{{- define "common.redis.values.keys.prefix" -}} + {{- if .subchart -}}redis.{{- else -}}{{- end -}} +{{- end -}} + +{{/* +Checks whether the redis chart's includes the standarizations (version >= 14) + +Usage: +{{ include "common.redis.values.standarized.version" (dict "context" $) }} +*/}} +{{- define "common.redis.values.standarized.version" -}} + + {{- $standarizedAuth := printf "%s%s" (include "common.redis.values.keys.prefix" .) "auth" -}} + {{- $standarizedAuthValues := include "common.utils.getValueFromKey" (dict "key" $standarizedAuth "context" .context) }} + + {{- if $standarizedAuthValues -}} + {{- true -}} + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_validations.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_validations.tpl new file mode 100644 index 00000000..9a814cf4 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_validations.tpl @@ -0,0 +1,46 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Validate values must not be empty. + +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. + +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/values.yaml new file mode 100644 index 00000000..f2df68e5 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/values.yaml @@ -0,0 +1,5 @@ +## bitnami/common +## It is required by CI/CD tools and processes. +## @skip exampleValue +## +exampleValue: common-chart diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/NOTES.txt b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/NOTES.txt new file mode 100644 index 00000000..e0474d4b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/NOTES.txt @@ -0,0 +1,89 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +{{- if .Values.diagnosticMode.enabled }} +The chart has been deployed in diagnostic mode. All probes have been disabled and the command has been overwritten with: + + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 4 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 4 }} + +Get the list of pods by executing: + + kubectl get pods --namespace {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Access the pod you want to debug by executing + + kubectl exec --namespace {{ .Release.Namespace }} -ti -- /opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash + +In order to replicate the container startup scripts execute this command: + + /opt/bitnami/scripts/postgresql/entrypoint.sh /opt/bitnami/scripts/postgresql/run.sh + +{{- else }} + +PostgreSQL can be accessed via port {{ include "postgresql.service.port" . }} on the following DNS names from within your cluster: + + {{ include "postgresql.primary.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - Read/Write connection + +{{- if eq .Values.architecture "replication" }} + + {{ include "postgresql.readReplica.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - Read only connection + +{{- end }} + +{{- $customUser := include "postgresql.username" . }} +{{- if and (not (empty $customUser)) (ne $customUser "postgres") .Values.auth.enablePostgresUser }} + +To get the password for "postgres" run: + + export POSTGRES_ADMIN_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "postgresql.secretName" . }} -o jsonpath="{.data.postgres-password}" | base64 -d) + +To get the password for "{{ $customUser }}" run: + + export POSTGRES_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "postgresql.secretName" . }} -o jsonpath="{.data.password}" | base64 -d) + +{{- else }} + +To get the password for "{{ default "postgres" $customUser }}" run: + + export POSTGRES_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "postgresql.secretName" . }} -o jsonpath="{.data.{{ ternary "password" "postgres-password" (and (not (empty $customUser)) (ne $customUser "postgres")) }}}" | base64 -d) + +{{- end }} + +To connect to your database run the following command: + + kubectl run {{ include "common.names.fullname" . }}-client --rm --tty -i --restart='Never' --namespace {{ .Release.Namespace }} --image {{ include "postgresql.image" . }} --env="PGPASSWORD=$POSTGRES_PASSWORD" \ + --command -- psql --host {{ include "postgresql.primary.fullname" . }} -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.database" . }} {{ include "postgresql.database" . }}{{- else }} postgres{{- end }} -p {{ include "postgresql.service.port" . }} + + > NOTE: If you access the container using bash, make sure that you execute "/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash" in order to avoid the error "psql: local user with ID {{ .Values.primary.containerSecurityContext.runAsUser }}} does not exist" + +To connect to your database from outside the cluster execute the following commands: + +{{- if contains "NodePort" .Values.primary.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "postgresql.primary.fullname" . }}) + PGPASSWORD="$POSTGRES_PASSWORD" psql --host $NODE_IP --port $NODE_PORT -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.database" . }} {{ include "postgresql.database" . }}{{- else }} postgres{{- end }} + +{{- else if contains "LoadBalancer" .Values.primary.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ include "postgresql.primary.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "postgresql.primary.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}") + PGPASSWORD="$POSTGRES_PASSWORD" psql --host $SERVICE_IP --port {{ include "postgresql.service.port" . }} -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.database" . }} {{ include "postgresql.database" . }}{{- else }} postgres{{- end }} + +{{- else if contains "ClusterIP" .Values.primary.service.type }} + + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "postgresql.primary.fullname" . }} {{ include "postgresql.service.port" . }}:{{ include "postgresql.service.port" . }} & + PGPASSWORD="$POSTGRES_PASSWORD" psql --host 127.0.0.1 -U {{ default "postgres" $customUser }} -d {{- if include "postgresql.database" . }} {{ include "postgresql.database" . }}{{- else }} postgres{{- end }} -p {{ include "postgresql.service.port" . }} + +{{- end }} +{{- end }} + +{{- include "postgresql.validateValues" . -}} +{{- include "common.warnings.rollingTag" .Values.image -}} +{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/_helpers.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/_helpers.tpl new file mode 100644 index 00000000..ae11d320 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/_helpers.tpl @@ -0,0 +1,382 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Create a default fully qualified app name for PostgreSQL Primary objects +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "postgresql.primary.fullname" -}} +{{- if eq .Values.architecture "replication" }} + {{- printf "%s-primary" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{- include "common.names.fullname" . -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified app name for PostgreSQL read-only replicas objects +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "postgresql.readReplica.fullname" -}} +{{- printf "%s-read" (include "common.names.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the default FQDN for PostgreSQL primary headless service +We truncate at 63 chars because of the DNS naming spec. +*/}} +{{- define "postgresql.primary.svc.headless" -}} +{{- printf "%s-hl" (include "postgresql.primary.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* +Create the default FQDN for PostgreSQL read-only replicas headless service +We truncate at 63 chars because of the DNS naming spec. +*/}} +{{- define "postgresql.readReplica.svc.headless" -}} +{{- printf "%s-hl" (include "postgresql.readReplica.fullname" .) | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{/* +Return the proper PostgreSQL image name +*/}} +{{- define "postgresql.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper PostgreSQL metrics image name +*/}} +{{- define "postgresql.metrics.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "postgresql.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "postgresql.imagePullSecrets" -}} +{{ include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image) "global" .Values.global) }} +{{- end -}} + +{{/* +Return the name for a custom user to create +*/}} +{{- define "postgresql.username" -}} +{{- if .Values.global.postgresql.auth.username }} + {{- .Values.global.postgresql.auth.username -}} +{{- else -}} + {{- .Values.auth.username -}} +{{- end -}} +{{- end -}} + +{{/* +Return the name for a custom database to create +*/}} +{{- define "postgresql.database" -}} +{{- if .Values.global.postgresql.auth.database }} + {{- .Values.global.postgresql.auth.database -}} +{{- else if .Values.auth.database -}} + {{- .Values.auth.database -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password secret. +*/}} +{{- define "postgresql.secretName" -}} +{{- if .Values.global.postgresql.auth.existingSecret }} + {{- printf "%s" (tpl .Values.global.postgresql.auth.existingSecret $) -}} +{{- else if .Values.auth.existingSecret -}} + {{- printf "%s" (tpl .Values.auth.existingSecret $) -}} +{{- else -}} + {{- printf "%s" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the replication-password key. +*/}} +{{- define "postgresql.replicationPasswordKey" -}} +{{- if or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret }} + {{- if .Values.global.postgresql.auth.secretKeys.replicationPasswordKey }} + {{- printf "%s" (tpl .Values.global.postgresql.auth.secretKeys.replicationPasswordKey $) -}} + {{- else if .Values.auth.secretKeys.replicationPasswordKey -}} + {{- printf "%s" (tpl .Values.auth.secretKeys.replicationPasswordKey $) -}} + {{- else -}} + {{- "replication-password" -}} + {{- end -}} +{{- else -}} + {{- "replication-password" -}} +{{- end -}} +{{- end -}} + +{{/* +Get the admin-password key. +*/}} +{{- define "postgresql.adminPasswordKey" -}} +{{- if or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret }} + {{- if .Values.global.postgresql.auth.secretKeys.adminPasswordKey }} + {{- printf "%s" (tpl .Values.global.postgresql.auth.secretKeys.adminPasswordKey $) -}} + {{- else if .Values.auth.secretKeys.adminPasswordKey -}} + {{- printf "%s" (tpl .Values.auth.secretKeys.adminPasswordKey $) -}} + {{- end -}} +{{- else -}} + {{- "postgres-password" -}} +{{- end -}} +{{- end -}} + +{{/* +Get the user-password key. +*/}} +{{- define "postgresql.userPasswordKey" -}} +{{- if or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret }} + {{- if or (empty (include "postgresql.username" .)) (eq (include "postgresql.username" .) "postgres") }} + {{- printf "%s" (include "postgresql.adminPasswordKey" .) -}} + {{- else -}} + {{- if .Values.global.postgresql.auth.secretKeys.userPasswordKey }} + {{- printf "%s" (tpl .Values.global.postgresql.auth.secretKeys.userPasswordKey $) -}} + {{- else if .Values.auth.secretKeys.userPasswordKey -}} + {{- printf "%s" (tpl .Values.auth.secretKeys.userPasswordKey $) -}} + {{- end -}} + {{- end -}} +{{- else -}} + {{- ternary "password" "postgres-password" (and (not (empty (include "postgresql.username" .))) (ne (include "postgresql.username" .) "postgres")) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created +*/}} +{{- define "postgresql.createSecret" -}} +{{- if not (or .Values.global.postgresql.auth.existingSecret .Values.auth.existingSecret) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL service port +*/}} +{{- define "postgresql.service.port" -}} +{{- if .Values.global.postgresql.service.ports.postgresql }} + {{- .Values.global.postgresql.service.ports.postgresql -}} +{{- else -}} + {{- .Values.primary.service.ports.postgresql -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL service port +*/}} +{{- define "postgresql.readReplica.service.port" -}} +{{- if .Values.global.postgresql.service.ports.postgresql }} + {{- .Values.global.postgresql.service.ports.postgresql -}} +{{- else -}} + {{- .Values.readReplicas.service.ports.postgresql -}} +{{- end -}} +{{- end -}} + +{{/* +Get the PostgreSQL primary configuration ConfigMap name. +*/}} +{{- define "postgresql.primary.configmapName" -}} +{{- if .Values.primary.existingConfigmap -}} + {{- printf "%s" (tpl .Values.primary.existingConfigmap $) -}} +{{- else -}} + {{- printf "%s-configuration" (include "postgresql.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for PostgreSQL primary with the configuration +*/}} +{{- define "postgresql.primary.createConfigmap" -}} +{{- if and (or .Values.primary.configuration .Values.primary.pgHbaConfiguration) (not .Values.primary.existingConfigmap) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* +Get the PostgreSQL primary extended configuration ConfigMap name. +*/}} +{{- define "postgresql.primary.extendedConfigmapName" -}} +{{- if .Values.primary.existingExtendedConfigmap -}} + {{- printf "%s" (tpl .Values.primary.existingExtendedConfigmap $) -}} +{{- else -}} + {{- printf "%s-extended-configuration" (include "postgresql.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap object should be created for PostgreSQL primary with the extended configuration +*/}} +{{- define "postgresql.primary.createExtendedConfigmap" -}} +{{- if and .Values.primary.extendedConfiguration (not .Values.primary.existingExtendedConfigmap) }} + {{- true -}} +{{- else -}} +{{- end -}} +{{- end -}} + +{{/* + Create the name of the service account to use + */}} +{{- define "postgresql.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "common.names.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap should be mounted with PostgreSQL configuration +*/}} +{{- define "postgresql.mountConfigurationCM" -}} +{{- if or .Values.primary.configuration .Values.primary.pgHbaConfiguration .Values.primary.existingConfigmap }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts ConfigMap name. +*/}} +{{- define "postgresql.initdb.scriptsCM" -}} +{{- if .Values.primary.initdb.scriptsConfigMap -}} + {{- printf "%s" (tpl .Values.primary.initdb.scriptsConfigMap $) -}} +{{- else -}} + {{- printf "%s-init-scripts" (include "postgresql.primary.fullname" .) -}} +{{- end -}} +{{- end -}} + +{/* +Return true if TLS is enabled for LDAP connection +*/}} +{{- define "postgresql.ldap.tls.enabled" -}} +{{- if and (kindIs "string" .Values.ldap.tls) (not (empty .Values.ldap.tls)) }} + {{- true -}} +{{- else if and (kindIs "map" .Values.ldap.tls) .Values.ldap.tls.enabled }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Get the readiness probe command +*/}} +{{- define "postgresql.readinessProbeCommand" -}} +{{- $customUser := include "postgresql.username" . }} +- | +{{- if (include "postgresql.database" .) }} + exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if .Values.tls.enabled }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} +{{- else }} + exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if .Values.tls.enabled }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} +{{- end }} +{{- if contains "bitnami/" .Values.image.repository }} + [ -f /opt/bitnami/postgresql/tmp/.initialized ] || [ -f /bitnami/postgresql/.initialized ] +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "postgresql.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "postgresql.validateValues.ldapConfigurationMethod" .) -}} +{{- $messages := append $messages (include "postgresql.validateValues.psp" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of Postgresql - If ldap.url is used then you don't need the other settings for ldap +*/}} +{{- define "postgresql.validateValues.ldapConfigurationMethod" -}} +{{- if and .Values.ldap.enabled (and (not (empty .Values.ldap.url)) (not (empty .Values.ldap.server))) }} +postgresql: ldap.url, ldap.server + You cannot set both `ldap.url` and `ldap.server` at the same time. + Please provide a unique way to configure LDAP. + More info at https://www.postgresql.org/docs/current/auth-ldap.html +{{- end -}} +{{- end -}} + +{{/* +Validate values of Postgresql - If PSP is enabled RBAC should be enabled too +*/}} +{{- define "postgresql.validateValues.psp" -}} +{{- if and .Values.psp.create (not .Values.rbac.create) }} +postgresql: psp.create, rbac.create + RBAC should be enabled if PSP is enabled in order for PSP to work. + More info at https://kubernetes.io/docs/concepts/policy/pod-security-policy/#authorizing-policies +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert file. +*/}} +{{- define "postgresql.tlsCert" -}} +{{- if .Values.tls.autoGenerated }} + {{- printf "/opt/bitnami/postgresql/certs/tls.crt" -}} +{{- else -}} + {{- required "Certificate filename is required when TLS in enabled" .Values.tls.certFilename | printf "/opt/bitnami/postgresql/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert key file. +*/}} +{{- define "postgresql.tlsCertKey" -}} +{{- if .Values.tls.autoGenerated }} + {{- printf "/opt/bitnami/postgresql/certs/tls.key" -}} +{{- else -}} +{{- required "Certificate Key filename is required when TLS in enabled" .Values.tls.certKeyFilename | printf "/opt/bitnami/postgresql/certs/%s" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "postgresql.tlsCACert" -}} +{{- if .Values.tls.autoGenerated }} + {{- printf "/opt/bitnami/postgresql/certs/ca.crt" -}} +{{- else -}} + {{- printf "/opt/bitnami/postgresql/certs/%s" .Values.tls.certCAFilename -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CRL file. +*/}} +{{- define "postgresql.tlsCRL" -}} +{{- if .Values.tls.crlFilename -}} +{{- printf "/opt/bitnami/postgresql/certs/%s" .Values.tls.crlFilename -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a TLS credentials secret object should be created +*/}} +{{- define "postgresql.createTlsSecret" -}} +{{- if and .Values.tls.autoGenerated (not .Values.tls.certificatesSecret) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "postgresql.tlsSecretName" -}} +{{- if .Values.tls.autoGenerated }} + {{- printf "%s-crt" (include "common.names.fullname" .) -}} +{{- else -}} + {{ required "A secret containing TLS certificates is required when TLS is enabled" .Values.tls.certificatesSecret }} +{{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/extra-list.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/extra-list.yaml new file mode 100644 index 00000000..9ac65f9e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/extra-list.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/networkpolicy-egress.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/networkpolicy-egress.yaml new file mode 100644 index 00000000..e8621474 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/networkpolicy-egress.yaml @@ -0,0 +1,32 @@ +{{- if and .Values.networkPolicy.enabled (or .Values.networkPolicy.egressRules.denyConnectionsToExternal .Values.networkPolicy.egressRules.customRules) }} +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ printf "%s-egress" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + {{- if .Values.networkPolicy.egressRules.denyConnectionsToExternal }} + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + - to: + - namespaceSelector: {} + {{- end }} + {{- if .Values.networkPolicy.egressRules.customRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.egressRules.customRules "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/configmap.yaml new file mode 100644 index 00000000..d654a225 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/configmap.yaml @@ -0,0 +1,24 @@ +{{- if (include "postgresql.primary.createConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-configuration" (include "postgresql.primary.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + {{- if .Values.primary.configuration }} + postgresql.conf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.configuration "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.primary.pgHbaConfiguration }} + pg_hba.conf: | + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.pgHbaConfiguration "context" $ ) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/extended-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/extended-configmap.yaml new file mode 100644 index 00000000..d129bd3b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/extended-configmap.yaml @@ -0,0 +1,18 @@ +{{- if (include "postgresql.primary.createExtendedConfigmap" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-extended-configuration" (include "postgresql.primary.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + override.conf: |- + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.extendedConfiguration "context" $ ) | nindent 4 }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/initialization-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/initialization-configmap.yaml new file mode 100644 index 00000000..d3d26cb8 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/initialization-configmap.yaml @@ -0,0 +1,15 @@ +{{- if and .Values.primary.initdb.scripts (not .Values.primary.initdb.scriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-init-scripts" (include "postgresql.primary.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: {{- include "common.tplvalues.render" (dict "value" .Values.primary.initdb.scripts "context" .) | nindent 2 }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/metrics-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/metrics-configmap.yaml new file mode 100644 index 00000000..8ad2f35f --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/metrics-configmap.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-metrics" (include "postgresql.primary.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + custom-metrics.yaml: {{ toYaml .Values.metrics.customMetrics | quote }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/metrics-svc.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/metrics-svc.yaml new file mode 100644 index 00000000..75a1b81b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/metrics-svc.yaml @@ -0,0 +1,31 @@ +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "postgresql.primary.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.metrics.service.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.service.annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + sessionAffinity: {{ .Values.metrics.service.sessionAffinity }} + {{- if .Values.metrics.service.clusterIP }} + clusterIP: {{ .Values.metrics.service.clusterIP }} + {{- end }} + ports: + - name: http-metrics + port: {{ .Values.metrics.service.ports.metrics }} + targetPort: http-metrics + selector: {{- include "common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: primary +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/networkpolicy.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/networkpolicy.yaml new file mode 100644 index 00000000..ce0052d4 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/networkpolicy.yaml @@ -0,0 +1,57 @@ +{{- if and .Values.networkPolicy.enabled (or .Values.networkPolicy.metrics.enabled .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.enabled) }} +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ printf "%s-ingress" (include "postgresql.primary.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }} + app.kubernetes.io/component: primary + ingress: + {{- if and .Values.metrics.enabled .Values.networkPolicy.metrics.enabled (or .Values.networkPolicy.metrics.namespaceSelector .Values.networkPolicy.metrics.podSelector) }} + - from: + {{- if .Values.networkPolicy.metrics.namespaceSelector }} + - namespaceSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.metrics.namespaceSelector "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.networkPolicy.metrics.podSelector }} + - podSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.metrics.podSelector "context" $) | nindent 14 }} + {{- end }} + ports: + - port: {{ .Values.metrics.containerPorts.metrics }} + {{- end }} + {{- if and .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.enabled (or .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.namespaceSelector .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.podSelector) }} + - from: + {{- if .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.namespaceSelector }} + - namespaceSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.namespaceSelector "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.podSelector }} + - podSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.podSelector "context" $) | nindent 14 }} + {{- end }} + ports: + - port: {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- if and .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.enabled (eq .Values.architecture "replication") }} + - from: + - podSelector: + matchLabels: {{- include "common.labels.matchLabels" . | nindent 14 }} + app.kubernetes.io/component: read + ports: + - port: {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- if .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.customRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.primaryAccessOnlyFrom.customRules "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/servicemonitor.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/servicemonitor.yaml new file mode 100644 index 00000000..c4a19fe0 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/servicemonitor.yaml @@ -0,0 +1,48 @@ +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "postgresql.primary.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.serviceMonitor.namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.metrics.serviceMonitor.labels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.labels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + app.kubernetes.io/component: metrics + endpoints: + - port: http-metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/statefulset.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/statefulset.yaml new file mode 100644 index 00000000..a1268821 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/statefulset.yaml @@ -0,0 +1,642 @@ +{{- $customUser := include "postgresql.username" . }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "postgresql.primary.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.primary.labels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.labels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.primary.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: 1 + serviceName: {{ include "postgresql.primary.svc.headless" . }} + {{- if .Values.primary.updateStrategy }} + updateStrategy: {{- toYaml .Values.primary.updateStrategy | nindent 4 }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }} + app.kubernetes.io/component: primary + template: + metadata: + name: {{ include "postgresql.primary.fullname" . }} + labels: {{- include "common.labels.standard" . | nindent 8 }} + app.kubernetes.io/component: primary + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.primary.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if (include "postgresql.primary.createConfigmap" .) }} + checksum/configuration: {{ include (print $.Template.BasePath "/primary/configmap.yaml") . | sha256sum }} + {{- end }} + {{- if (include "postgresql.primary.createExtendedConfigmap" .) }} + checksum/extended-configuration: {{ include (print $.Template.BasePath "/primary/extended-configmap.yaml") . | sha256sum }} + {{- end }} + {{- if .Values.primary.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- if .Values.primary.extraPodSpec }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraPodSpec "context" $) | nindent 6 }} + {{- end }} + serviceAccountName: {{ include "postgresql.serviceAccountName" . }} + {{- include "postgresql.imagePullSecrets" . | nindent 6 }} + {{- if .Values.primary.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.primary.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.primary.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAffinityPreset "component" "primary" "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAntiAffinityPreset "component" "primary" "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.primary.nodeAffinityPreset.type "key" .Values.primary.nodeAffinityPreset.key "values" .Values.primary.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.primary.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.primary.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.primary.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.primary.priorityClassName }} + priorityClassName: {{ .Values.primary.priorityClassName }} + {{- end }} + {{- if .Values.primary.schedulerName }} + schedulerName: {{ .Values.primary.schedulerName | quote }} + {{- end }} + {{- if .Values.primary.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.primary.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.primary.podSecurityContext.enabled }} + securityContext: {{- omit .Values.primary.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + hostNetwork: {{ .Values.primary.hostNetwork }} + hostIPC: {{ .Values.primary.hostIPC }} + initContainers: + {{- if and .Values.tls.enabled (not .Values.volumePermissions.enabled) }} + - name: copy-certs + image: {{ include "postgresql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.primary.resources }} + resources: {{- toYaml .Values.primary.resources | nindent 12 }} + {{- end }} + # We don't require a privileged container in this case + {{- if .Values.primary.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.primary.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -ec + - | + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + chmod 600 {{ include "postgresql.tlsCertKey" . }} + volumeMounts: + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- else if and .Values.volumePermissions.enabled (or .Values.primary.persistence.enabled .Values.shmVolume.enabled) }} + - name: init-chmod-data + image: {{ include "postgresql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -ec + - | + {{- if .Values.primary.persistence.enabled }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.primary.persistence.mountPath }} + {{- else }} + chown {{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }} {{ .Values.primary.persistence.mountPath }} + {{- end }} + mkdir -p {{ .Values.primary.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.primary.persistence.mountPath }}/conf {{- end }} + chmod 700 {{ .Values.primary.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.primary.persistence.mountPath }}/conf {{- end }} + find {{ .Values.primary.persistence.mountPath }} -mindepth 1 -maxdepth 1 {{- if not (include "postgresql.mountConfigurationCM" .) }} -not -name "conf" {{- end }} -not -name ".snapshot" -not -name "lost+found" | \ + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + xargs -r chown -R `id -u`:`id -G | cut -d " " -f2` + {{- else }} + xargs -r chown -R {{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }} + {{- end }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + chmod -R 777 /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/ + {{- else }} + chown -R {{ .Values.primary.containerSecurityContext.runAsUser }}:{{ .Values.primary.podSecurityContext.fsGroup }} /opt/bitnami/postgresql/certs/ + {{- end }} + chmod 600 {{ include "postgresql.tlsCertKey" . }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.primary.persistence.enabled }} + - name: data + mountPath: {{ .Values.primary.persistence.mountPath }} + {{- if .Values.primary.persistence.subPath }} + subPath: {{ .Values.primary.persistence.subPath }} + {{- end }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- end }} + {{- end }} + {{- if .Values.primary.initContainers }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.initContainers "context" $ ) | nindent 8 }} + {{- end }} + containers: + - name: postgresql + image: {{ include "postgresql.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.primary.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.primary.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.primary.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.primary.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.primary.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.primary.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: POSTGRESQL_PORT_NUMBER + value: {{ .Values.containerPorts.postgresql | quote }} + - name: POSTGRESQL_VOLUME_DIR + value: {{ .Values.primary.persistence.mountPath | quote }} + {{- if .Values.primary.persistence.mountPath }} + - name: PGDATA + value: {{ .Values.postgresqlDataDir | quote }} + {{- end }} + # Authentication + {{- if and (not (empty $customUser)) (ne $customUser "postgres") }} + - name: POSTGRES_USER + value: {{ $customUser | quote }} + {{- if .Values.auth.enablePostgresUser }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgres-password" + {{- else }} + - name: POSTGRES_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.secretName" . }} + key: {{ include "postgresql.adminPasswordKey" . }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_PASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (ternary "password" "postgres-password" (and (not (empty $customUser)) (ne $customUser "postgres"))) }} + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.secretName" . }} + key: {{ include "postgresql.userPasswordKey" . }} + {{- end }} + {{- if (include "postgresql.database" .) }} + - name: POSTGRES_DB + value: {{ (include "postgresql.database" .) | quote }} + {{- end }} + # Replication + {{- if or (eq .Values.architecture "replication") .Values.primary.standby.enabled }} + - name: POSTGRES_REPLICATION_MODE + value: {{ ternary "slave" "master" .Values.primary.standby.enabled | quote }} + - name: POSTGRES_REPLICATION_USER + value: {{ .Values.auth.replicationUsername | quote }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_REPLICATION_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/replication-password" + {{- else }} + - name: POSTGRES_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.secretName" . }} + key: {{ include "postgresql.replicationPasswordKey" . }} + {{- end }} + {{- if not (eq .Values.replication.synchronousCommit "off") }} + - name: POSTGRES_SYNCHRONOUS_COMMIT_MODE + value: {{ .Values.replication.synchronousCommit | quote }} + - name: POSTGRES_NUM_SYNCHRONOUS_REPLICAS + value: {{ .Values.replication.numSynchronousReplicas | quote }} + {{- end }} + - name: POSTGRES_CLUSTER_APP_NAME + value: {{ .Values.replication.applicationName }} + {{- end }} + # Initdb + {{- if .Values.primary.initdb.args }} + - name: POSTGRES_INITDB_ARGS + value: {{ .Values.primary.initdb.args | quote }} + {{- end }} + {{- if .Values.primary.initdb.postgresqlWalDir }} + - name: POSTGRES_INITDB_WALDIR + value: {{ .Values.primary.initdb.postgresqlWalDir | quote }} + {{- end }} + {{- if .Values.primary.initdb.user }} + - name: POSTGRESQL_INITSCRIPTS_USERNAME + value: {{ .Values.primary.initdb.user }} + {{- end }} + {{- if .Values.primary.initdb.password }} + - name: POSTGRESQL_INITSCRIPTS_PASSWORD + value: {{ .Values.primary.initdb.password | quote }} + {{- end }} + # Standby + {{- if .Values.primary.standby.enabled }} + - name: POSTGRES_MASTER_HOST + value: {{ .Values.primary.standby.primaryHost }} + - name: POSTGRES_MASTER_PORT_NUMBER + value: {{ .Values.primary.standby.primaryPort | quote }} + {{- end }} + # LDAP + - name: POSTGRESQL_ENABLE_LDAP + value: {{ ternary "yes" "no" .Values.ldap.enabled | quote }} + {{- if .Values.ldap.enabled }} + {{- if or .Values.ldap.url .Values.ldap.uri }} + - name: POSTGRESQL_LDAP_URL + value: {{ coalesce .Values.ldap.url .Values.ldap.uri }} + {{- else }} + - name: POSTGRESQL_LDAP_SERVER + value: {{ .Values.ldap.server }} + - name: POSTGRESQL_LDAP_PORT + value: {{ .Values.ldap.port | quote }} + - name: POSTGRESQL_LDAP_SCHEME + value: {{ .Values.ldap.scheme }} + {{- if (include "postgresql.ldap.tls.enabled" .) }} + - name: POSTGRESQL_LDAP_TLS + value: "1" + {{- end }} + - name: POSTGRESQL_LDAP_PREFIX + value: {{ .Values.ldap.prefix | quote }} + - name: POSTGRESQL_LDAP_SUFFIX + value: {{ .Values.ldap.suffix | quote }} + - name: POSTGRESQL_LDAP_BASE_DN + value: {{ coalesce .Values.ldap.baseDN .Values.ldap.basedn }} + - name: POSTGRESQL_LDAP_BIND_DN + value: {{ coalesce .Values.ldap.bindDN .Values.ldap.binddn}} + {{- if or (not (empty .Values.ldap.bind_password)) (not (empty .Values.ldap.bindpw)) }} + - name: POSTGRESQL_LDAP_BIND_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.secretName" . }} + key: ldap-password + {{- end }} + - name: POSTGRESQL_LDAP_SEARCH_ATTR + value: {{ coalesce .Values.ldap.search_attr .Values.ldap.searchAttribute }} + - name: POSTGRESQL_LDAP_SEARCH_FILTER + value: {{ coalesce .Values.ldap.search_filter .Values.ldap.searchFilter }} + {{- end }} + {{- end }} + # TLS + - name: POSTGRESQL_ENABLE_TLS + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS + value: {{ ternary "yes" "no" .Values.tls.preferServerCiphers | quote }} + - name: POSTGRESQL_TLS_CERT_FILE + value: {{ include "postgresql.tlsCert" . }} + - name: POSTGRESQL_TLS_KEY_FILE + value: {{ include "postgresql.tlsCertKey" . }} + {{- if .Values.tls.certCAFilename }} + - name: POSTGRESQL_TLS_CA_FILE + value: {{ include "postgresql.tlsCACert" . }} + {{- end }} + {{- if .Values.tls.crlFilename }} + - name: POSTGRESQL_TLS_CRL_FILE + value: {{ include "postgresql.tlsCRL" . }} + {{- end }} + {{- end }} + # Audit + - name: POSTGRESQL_LOG_HOSTNAME + value: {{ .Values.audit.logHostname | quote }} + - name: POSTGRESQL_LOG_CONNECTIONS + value: {{ .Values.audit.logConnections | quote }} + - name: POSTGRESQL_LOG_DISCONNECTIONS + value: {{ .Values.audit.logDisconnections | quote }} + {{- if .Values.audit.logLinePrefix }} + - name: POSTGRESQL_LOG_LINE_PREFIX + value: {{ .Values.audit.logLinePrefix | quote }} + {{- end }} + {{- if .Values.audit.logTimezone }} + - name: POSTGRESQL_LOG_TIMEZONE + value: {{ .Values.audit.logTimezone | quote }} + {{- end }} + {{- if .Values.audit.pgAuditLog }} + - name: POSTGRESQL_PGAUDIT_LOG + value: {{ .Values.audit.pgAuditLog | quote }} + {{- end }} + - name: POSTGRESQL_PGAUDIT_LOG_CATALOG + value: {{ .Values.audit.pgAuditLogCatalog | quote }} + # Others + - name: POSTGRESQL_CLIENT_MIN_MESSAGES + value: {{ .Values.audit.clientMinMessages | quote }} + - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES + value: {{ .Values.postgresqlSharedPreloadLibraries | quote }} + {{- if .Values.primary.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.primary.extraEnvVarsCM .Values.primary.extraEnvVarsSecret }} + envFrom: + {{- if .Values.primary.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.primary.extraEnvVarsCM }} + {{- end }} + {{- if .Values.primary.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.primary.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: tcp-postgresql + containerPort: {{ .Values.containerPorts.postgresql }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.primary.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.database" .) }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- else }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- else if .Values.primary.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customStartupProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.primary.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.database" .) }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- else }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- else if .Values.primary.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customLivenessProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.primary.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.primary.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + - -e + {{- include "postgresql.readinessProbeCommand" . | nindent 16 }} + {{- else if .Values.primary.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.primary.customReadinessProbe "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.primary.resources }} + resources: {{- toYaml .Values.primary.resources | nindent 12 }} + {{- end }} + {{- if .Values.primary.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.primary.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + {{- if or .Values.primary.initdb.scriptsConfigMap .Values.primary.initdb.scripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d/ + {{- end }} + {{- if .Values.primary.initdb.scriptsSecret }} + - name: custom-init-scripts-secret + mountPath: /docker-entrypoint-initdb.d/secret + {{- end }} + {{- if or .Values.primary.extendedConfiguration .Values.primary.existingExtendedConfigmap }} + - name: postgresql-extended-config + mountPath: /bitnami/postgresql/conf/conf.d/ + {{- end }} + {{- if .Values.auth.usePasswordFiles }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + readOnly: true + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.primary.persistence.enabled }} + - name: data + mountPath: {{ .Values.primary.persistence.mountPath }} + {{- if .Values.primary.persistence.subPath }} + subPath: {{ .Values.primary.persistence.subPath }} + {{- end }} + {{- end }} + {{- if or .Values.primary.configuration .Values.primary.pgHbaConfiguration .Values.primary.existingConfigmap }} + - name: postgresql-config + mountPath: /bitnami/postgresql/conf + {{- end }} + {{- if .Values.primary.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "postgresql.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.customMetrics }} + args: ["--extend.query-path", "/conf/custom-metrics.yaml"] + {{- end }} + env: + {{- $database := required "In order to enable metrics you need to specify a database (.Values.auth.database or .Values.global.postgresql.auth.database)" (include "postgresql.database" .) }} + {{- $sslmode := ternary "require" "disable" .Values.tls.enabled }} + {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} + - name: DATA_SOURCE_NAME + value: {{ printf "host=127.0.0.1 port=%d user=%s sslmode=%s sslcert=%s sslkey=%s" (int (include "postgresql.service.port" .)) (default "postgres" $customUser) $sslmode (include "postgresql.tlsCert" .) (include "postgresql.tlsCertKey" .) }} + {{- else }} + - name: DATA_SOURCE_URI + value: {{ printf "127.0.0.1:%d/%s?sslmode=%s" (int (include "postgresql.service.port" .)) $database $sslmode }} + {{- end }} + {{- if .Values.auth.usePasswordFiles }} + - name: DATA_SOURCE_PASS_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (ternary "password" "postgres-password" (and (not (empty $customUser)) (ne $customUser "postgres"))) }} + {{- else }} + - name: DATA_SOURCE_PASS + valueFrom: + secretKeyRef: + name: {{ include "postgresql.secretName" . }} + key: {{ include "postgresql.userPasswordKey" . }} + {{- end }} + - name: DATA_SOURCE_USER + value: {{ default "postgres" $customUser | quote }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.metrics.containerPorts.metrics }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http-metrics + {{- else if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http-metrics + {{- else if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http-metrics + {{- else if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- end }} + {{- end }} + volumeMounts: + {{- if .Values.auth.usePasswordFiles }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.customMetrics }} + - name: custom-metrics + mountPath: /conf + readOnly: true + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.primary.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.sidecars "context" $ ) | nindent 8 }} + {{- end }} + volumes: + {{- if or .Values.primary.configuration .Values.primary.pgHbaConfiguration .Values.primary.existingConfigmap }} + - name: postgresql-config + configMap: + name: {{ include "postgresql.primary.configmapName" . }} + {{- end }} + {{- if or .Values.primary.extendedConfiguration .Values.primary.existingExtendedConfigmap }} + - name: postgresql-extended-config + configMap: + name: {{ include "postgresql.primary.extendedConfigmapName" . }} + {{- end }} + {{- if .Values.auth.usePasswordFiles }} + - name: postgresql-password + secret: + secretName: {{ include "postgresql.secretName" . }} + {{- end }} + {{- if or .Values.primary.initdb.scriptsConfigMap .Values.primary.initdb.scripts }} + - name: custom-init-scripts + configMap: + name: {{ include "postgresql.initdb.scriptsCM" . }} + {{- end }} + {{- if .Values.primary.initdb.scriptsSecret }} + - name: custom-init-scripts-secret + secret: + secretName: {{ tpl .Values.primary.initdb.scriptsSecret $ }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + secret: + secretName: {{ include "postgresql.tlsSecretName" . }} + - name: postgresql-certificates + emptyDir: {} + {{- end }} + {{- if .Values.primary.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} + - name: custom-metrics + configMap: + name: {{ printf "%s-metrics" (include "common.names.fullname" .) }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + emptyDir: + medium: Memory + {{- if .Values.shmVolume.sizeLimit }} + sizeLimit: {{ .Values.shmVolume.sizeLimit }} + {{- end }} + {{- end }} + {{- if and .Values.primary.persistence.enabled .Values.primary.persistence.existingClaim }} + - name: data + persistentVolumeClaim: + claimName: {{ tpl .Values.primary.persistence.existingClaim $ }} + {{- else if not .Values.primary.persistence.enabled }} + - name: data + emptyDir: {} + {{- else }} + volumeClaimTemplates: + - metadata: + name: data + {{- if .Values.primary.persistence.annotations }} + annotations: {{- toYaml .Values.primary.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.primary.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + {{- if .Values.primary.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + resources: + requests: + storage: {{ .Values.primary.persistence.size | quote }} + {{- if .Values.primary.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.persistence.selector "context" $) | nindent 10 }} + {{- end }} + {{- include "common.storage.class" (dict "persistence" .Values.primary.persistence "global" .Values.global) | nindent 8 }} + {{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/svc-headless.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/svc-headless.yaml new file mode 100644 index 00000000..b7826318 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/svc-headless.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postgresql.primary.svc.headless" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + app.kubernetes.io/component: primary + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + # Use this annotation in addition to the actual publishNotReadyAddresses + # field below because the annotation will stop being respected soon but the + # field is broken in some versions of Kubernetes: + # https://github.com/kubernetes/kubernetes/issues/58662 + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" +spec: + type: ClusterIP + clusterIP: None + # We want all pods in the StatefulSet to have their addresses published for + # the sake of the other Postgresql pods even before they're ready, since they + # have to be able to talk to each other in order to become ready. + publishNotReadyAddresses: true + ports: + - name: tcp-postgresql + port: {{ template "postgresql.service.port" . }} + targetPort: tcp-postgresql + selector: {{- include "common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: primary diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/svc.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/svc.yaml new file mode 100644 index 00000000..cf184809 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/svc.yaml @@ -0,0 +1,51 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postgresql.primary.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + app.kubernetes.io/component: primary + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.primary.service.annotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.primary.service.type }} + {{- if or (eq .Values.primary.service.type "LoadBalancer") (eq .Values.primary.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.primary.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.primary.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.primary.service.type "LoadBalancer") (not (empty .Values.primary.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.primary.service.loadBalancerIP }} + {{- end }} + {{- if and .Values.primary.service.clusterIP (eq .Values.primary.service.type "ClusterIP") }} + clusterIP: {{ .Values.primary.service.clusterIP }} + {{- end }} + {{- if .Values.primary.service.sessionAffinity }} + sessionAffinity: {{ .Values.primary.service.sessionAffinity }} + {{- end }} + {{- if .Values.primary.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-postgresql + port: {{ template "postgresql.service.port" . }} + targetPort: tcp-postgresql + {{- if and (or (eq .Values.primary.service.type "NodePort") (eq .Values.primary.service.type "LoadBalancer")) (not (empty .Values.primary.service.nodePorts.postgresql)) }} + nodePort: {{ .Values.primary.service.nodePorts.postgresql }} + {{- else if eq .Values.primary.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.primary.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.primary.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + selector: {{- include "common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: primary diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/prometheusrule.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/prometheusrule.yaml new file mode 100644 index 00000000..24be7100 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/prometheusrule.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.prometheusRule.namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.metrics.prometheusRule.labels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.labels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "common.names.fullname" . }} + rules: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.prometheusRule.rules "context" $ ) | nindent 8 }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/psp.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/psp.yaml new file mode 100644 index 00000000..48d11754 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/psp.yaml @@ -0,0 +1,41 @@ +{{- $pspAvailable := (semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .)) -}} +{{- if and $pspAvailable .Values.psp.create }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + privileged: false + volumes: + - 'configMap' + - 'secret' + - 'persistentVolumeClaim' + - 'emptyDir' + - 'projected' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/metrics-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/metrics-configmap.yaml new file mode 100644 index 00000000..ddaae75b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/metrics-configmap.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-metrics" (include "postgresql.readReplica.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + custom-metrics.yaml: {{ toYaml .Values.metrics.customMetrics | quote }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/metrics-svc.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/metrics-svc.yaml new file mode 100644 index 00000000..846d853a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/metrics-svc.yaml @@ -0,0 +1,31 @@ +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-metrics" (include "postgresql.readReplica.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.metrics.service.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.service.annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + sessionAffinity: {{ .Values.metrics.service.sessionAffinity }} + {{- if .Values.metrics.service.clusterIP }} + clusterIP: {{ .Values.metrics.service.clusterIP }} + {{- end }} + ports: + - name: http-metrics + port: {{ .Values.metrics.service.ports.metrics }} + targetPort: http-metrics + selector: {{- include "common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: read +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/networkpolicy.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/networkpolicy.yaml new file mode 100644 index 00000000..c969cd7a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/networkpolicy.yaml @@ -0,0 +1,36 @@ +{{- if and .Values.networkPolicy.enabled (eq .Values.architecture "replication") .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.enabled }} +apiVersion: {{ include "common.capabilities.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ printf "%s-ingress" (include "postgresql.readReplica.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: read + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }} + app.kubernetes.io/component: read + ingress: + {{- if and .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.enabled (or .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.namespaceSelector .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.podSelector) }} + - from: + {{- if .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.namespaceSelector }} + - namespaceSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.namespaceSelector "context" $) | nindent 14 }} + {{- end }} + {{- if .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.podSelector }} + - podSelector: + matchLabels: {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.podSelector "context" $) | nindent 14 }} + {{- end }} + ports: + - port: {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- if .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.customRules }} + {{- include "common.tplvalues.render" (dict "value" .Values.networkPolicy.ingressRules.readReplicasAccessOnlyFrom.customRules "context" $) | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/servicemonitor.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/servicemonitor.yaml new file mode 100644 index 00000000..aa06b073 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/servicemonitor.yaml @@ -0,0 +1,48 @@ +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "postgresql.readReplica.fullname" . }} + namespace: {{ default .Release.Namespace .Values.metrics.serviceMonitor.namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: metrics + {{- if .Values.metrics.serviceMonitor.labels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.labels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.metrics.serviceMonitor.jobLabel }} + jobLabel: {{ .Values.metrics.serviceMonitor.jobLabel }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }} + {{- if .Values.metrics.serviceMonitor.selector }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.serviceMonitor.selector "context" $) | nindent 6 }} + {{- end }} + app.kubernetes.io/component: metrics + endpoints: + - port: http-metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.relabelings }} + relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 6 }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ .Values.metrics.serviceMonitor.honorLabels }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/statefulset.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/statefulset.yaml new file mode 100644 index 00000000..fa986c10 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/statefulset.yaml @@ -0,0 +1,523 @@ +{{- if eq .Values.architecture "replication" }} +{{- $customUser := include "postgresql.username" . }} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ include "postgresql.readReplica.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: read + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.readReplicas.labels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.labels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.readReplicas.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.readReplicas.replicaCount }} + serviceName: {{ include "postgresql.readReplica.svc.headless" . }} + {{- if .Values.readReplicas.updateStrategy }} + updateStrategy: {{- toYaml .Values.readReplicas.updateStrategy | nindent 4 }} + {{- end }} + selector: + matchLabels: {{- include "common.labels.matchLabels" . | nindent 6 }} + app.kubernetes.io/component: read + template: + metadata: + name: {{ include "postgresql.readReplica.fullname" . }} + labels: {{- include "common.labels.standard" . | nindent 8 }} + app.kubernetes.io/component: read + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 8 }} + {{- end }} + {{- if .Values.readReplicas.podLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.podLabels "context" $ ) | nindent 8 }} + {{- end }} + annotations: + {{- if .Values.readReplicas.podAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.podAnnotations "context" $ ) | nindent 8 }} + {{- end }} + spec: + {{- if .Values.readReplicas.extraPodSpec }} + {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.extraPodSpec "context" $) | nindent 6 }} + {{- end }} + serviceAccountName: {{ include "postgresql.serviceAccountName" . }} + {{- include "postgresql.imagePullSecrets" . | nindent 6 }} + {{- if .Values.readReplicas.hostAliases }} + hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.readReplicas.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.readReplicas.podAffinityPreset "component" "read" "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.readReplicas.podAntiAffinityPreset "component" "read" "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.readReplicas.nodeAffinityPreset.type "key" .Values.readReplicas.nodeAffinityPreset.key "values" .Values.readReplicas.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.readReplicas.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.readReplicas.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.readReplicas.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.topologySpreadConstraints "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.readReplicas.priorityClassName }} + priorityClassName: {{ .Values.readReplicas.priorityClassName }} + {{- end }} + {{- if .Values.readReplicas.schedulerName }} + schedulerName: {{ .Values.readReplicas.schedulerName | quote }} + {{- end }} + {{- if .Values.readReplicas.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.readReplicas.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.readReplicas.podSecurityContext.enabled }} + securityContext: {{- omit .Values.readReplicas.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + hostNetwork: {{ .Values.readReplicas.hostNetwork }} + hostIPC: {{ .Values.readReplicas.hostIPC }} + initContainers: + {{- if and .Values.tls.enabled (not .Values.volumePermissions.enabled) }} + - name: copy-certs + image: {{ include "postgresql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.readReplicas.resources }} + resources: {{- toYaml .Values.readReplicas.resources | nindent 12 }} + {{- end }} + # We don't require a privileged container in this case + {{- if .Values.readReplicas.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.readReplicas.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -ec + - | + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + chmod 600 {{ include "postgresql.tlsCertKey" . }} + volumeMounts: + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- else if and .Values.volumePermissions.enabled (or .Values.readReplicas.persistence.enabled .Values.shmVolume.enabled) }} + - name: init-chmod-data + image: {{ include "postgresql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.readReplicas.resources }} + resources: {{- toYaml .Values.readReplicas.resources | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -ec + - | + {{- if .Values.readReplicas.persistence.enabled }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.readReplicas.persistence.mountPath }} + {{- else }} + chown {{ .Values.readReplicas.containerSecurityContext.runAsUser }}:{{ .Values.readReplicas.podSecurityContext.fsGroup }} {{ .Values.readReplicas.persistence.mountPath }} + {{- end }} + mkdir -p {{ .Values.readReplicas.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.readReplicas.persistence.mountPath }}/conf {{- end }} + chmod 700 {{ .Values.readReplicas.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.readReplicas.persistence.mountPath }}/conf {{- end }} + find {{ .Values.readReplicas.persistence.mountPath }} -mindepth 1 -maxdepth 1 {{- if not (include "postgresql.mountConfigurationCM" .) }} -not -name "conf" {{- end }} -not -name ".snapshot" -not -name "lost+found" | \ + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + xargs -r chown -R `id -u`:`id -G | cut -d " " -f2` + {{- else }} + xargs -r chown -R {{ .Values.readReplicas.containerSecurityContext.runAsUser }}:{{ .Values.readReplicas.podSecurityContext.fsGroup }} + {{- end }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + chmod -R 777 /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/ + {{- else }} + chown -R {{ .Values.readReplicas.containerSecurityContext.runAsUser }}:{{ .Values.readReplicas.podSecurityContext.fsGroup }} /opt/bitnami/postgresql/certs/ + {{- end }} + chmod 600 {{ include "postgresql.tlsCertKey" . }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.containerSecurityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.containerSecurityContext | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + {{ if .Values.readReplicas.persistence.enabled }} + - name: data + mountPath: {{ .Values.readReplicas.persistence.mountPath }} + {{- if .Values.readReplicas.persistence.subPath }} + subPath: {{ .Values.readReplicas.persistence.subPath }} + {{- end }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- end }} + {{- end }} + {{- if .Values.readReplicas.initContainers }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.initContainers "context" $ ) | nindent 8 }} + {{- end }} + containers: + - name: postgresql + image: {{ include "postgresql.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.readReplicas.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.readReplicas.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.readReplicas.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.readReplicas.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.args "context" $) | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" (or .Values.image.debug .Values.diagnosticMode.enabled) | quote }} + - name: POSTGRESQL_PORT_NUMBER + value: {{ .Values.containerPorts.postgresql | quote }} + - name: POSTGRESQL_VOLUME_DIR + value: {{ .Values.readReplicas.persistence.mountPath | quote }} + {{- if .Values.readReplicas.persistence.mountPath }} + - name: PGDATA + value: {{ .Values.postgresqlDataDir | quote }} + {{- end }} + # Authentication + {{- if and (not (empty $customUser)) (ne $customUser "postgres") .Values.auth.enablePostgresUser }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgres-password" + {{- else }} + - name: POSTGRES_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.secretName" . }} + key: {{ include "postgresql.adminPasswordKey" . }} + {{- end }} + {{- end }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_PASSWORD_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (ternary "password" "postgres-password" (and (not (empty $customUser)) (ne $customUser "postgres"))) }} + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.secretName" . }} + key: {{ include "postgresql.userPasswordKey" . }} + {{- end }} + # Replication + - name: POSTGRES_REPLICATION_MODE + value: "slave" + - name: POSTGRES_REPLICATION_USER + value: {{ .Values.auth.replicationUsername | quote }} + {{- if .Values.auth.usePasswordFiles }} + - name: POSTGRES_REPLICATION_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/replication-password" + {{- else }} + - name: POSTGRES_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "postgresql.secretName" . }} + key: {{ include "postgresql.replicationPasswordKey" . }} + {{- end }} + - name: POSTGRES_CLUSTER_APP_NAME + value: {{ .Values.replication.applicationName }} + - name: POSTGRES_MASTER_HOST + value: {{ include "postgresql.primary.fullname" . }} + - name: POSTGRES_MASTER_PORT_NUMBER + value: {{ include "postgresql.service.port" . | quote }} + # TLS + - name: POSTGRESQL_ENABLE_TLS + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS + value: {{ ternary "yes" "no" .Values.tls.preferServerCiphers | quote }} + - name: POSTGRESQL_TLS_CERT_FILE + value: {{ include "postgresql.tlsCert" . }} + - name: POSTGRESQL_TLS_KEY_FILE + value: {{ include "postgresql.tlsCertKey" . }} + {{- if .Values.tls.certCAFilename }} + - name: POSTGRESQL_TLS_CA_FILE + value: {{ include "postgresql.tlsCACert" . }} + {{- end }} + {{- if .Values.tls.crlFilename }} + - name: POSTGRESQL_TLS_CRL_FILE + value: {{ include "postgresql.tlsCRL" . }} + {{- end }} + {{- end }} + # Audit + - name: POSTGRESQL_LOG_HOSTNAME + value: {{ .Values.audit.logHostname | quote }} + - name: POSTGRESQL_LOG_CONNECTIONS + value: {{ .Values.audit.logConnections | quote }} + - name: POSTGRESQL_LOG_DISCONNECTIONS + value: {{ .Values.audit.logDisconnections | quote }} + {{- if .Values.audit.logLinePrefix }} + - name: POSTGRESQL_LOG_LINE_PREFIX + value: {{ .Values.audit.logLinePrefix | quote }} + {{- end }} + {{- if .Values.audit.logTimezone }} + - name: POSTGRESQL_LOG_TIMEZONE + value: {{ .Values.audit.logTimezone | quote }} + {{- end }} + {{- if .Values.audit.pgAuditLog }} + - name: POSTGRESQL_PGAUDIT_LOG + value: {{ .Values.audit.pgAuditLog | quote }} + {{- end }} + - name: POSTGRESQL_PGAUDIT_LOG_CATALOG + value: {{ .Values.audit.pgAuditLogCatalog | quote }} + # Others + - name: POSTGRESQL_CLIENT_MIN_MESSAGES + value: {{ .Values.audit.clientMinMessages | quote }} + - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES + value: {{ .Values.postgresqlSharedPreloadLibraries | quote }} + {{- if .Values.readReplicas.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if or .Values.readReplicas.extraEnvVarsCM .Values.readReplicas.extraEnvVarsSecret }} + envFrom: + {{- if .Values.readReplicas.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.readReplicas.extraEnvVarsCM }} + {{- end }} + {{- if .Values.readReplicas.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.readReplicas.extraEnvVarsSecret }} + {{- end }} + {{- end }} + ports: + - name: tcp-postgresql + containerPort: {{ .Values.containerPorts.postgresql }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.readReplicas.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readReplicas.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.database" .) }} + - exec pg_isready -U {{ default "postgres" $customUser| quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- else }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- else if .Values.readReplicas.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.customStartupProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.readReplicas.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readReplicas.livenessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.database" .) }} + - exec pg_isready -U {{ default "postgres" $customUser | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- else }} + - exec pg_isready -U {{default "postgres" $customUser | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ .Values.containerPorts.postgresql }} + {{- end }} + {{- else if .Values.readReplicas.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.customLivenessProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.readReplicas.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readReplicas.readinessProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - /bin/sh + - -c + - -e + {{- include "postgresql.readinessProbeCommand" . | nindent 16 }} + {{- else if .Values.readReplicas.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.customReadinessProbe "context" $) | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.readReplicas.resources }} + resources: {{- toYaml .Values.readReplicas.resources | nindent 12 }} + {{- end }} + {{- if .Values.readReplicas.lifecycleHooks }} + lifecycle: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.auth.usePasswordFiles }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + readOnly: true + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.readReplicas.persistence.enabled }} + - name: data + mountPath: {{ .Values.readReplicas.persistence.mountPath }} + {{- if .Values.readReplicas.persistence.subPath }} + subPath: {{ .Values.readReplicas.persistence.subPath }} + {{- end }} + {{- end }} + {{- if .Values.readReplicas.extraVolumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: {{ include "postgresql.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.metrics.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.metrics.customMetrics }} + args: [ "--extend.query-path", "/conf/custom-metrics.yaml" ] + {{- end }} + env: + {{- $database := required "In order to enable metrics you need to specify a database (.Values.auth.database or .Values.global.postgresql.auth.database)" (include "postgresql.database" .) }} + {{- $sslmode := ternary "require" "disable" .Values.tls.enabled }} + {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} + - name: DATA_SOURCE_NAME + value: {{ printf "host=127.0.0.1 port=%d user=%s sslmode=%s sslcert=%s sslkey=%s" (int (include "postgresql.service.port" .)) (default "postgres" $customUser | quote) $sslmode (include "postgresql.tlsCert" .) (include "postgresql.tlsCertKey" .) }} + {{- else }} + - name: DATA_SOURCE_URI + value: {{ printf "127.0.0.1:%d/%s?sslmode=%s" (int (include "postgresql.service.port" .)) $database $sslmode }} + {{- end }} + {{- if .Values.auth.usePasswordFiles }} + - name: DATA_SOURCE_PASS_FILE + value: {{ printf "/opt/bitnami/postgresql/secrets/%s" (ternary "password" "postgres-password" (and (not (empty $customUser)) (ne $customUser "postgres"))) }} + {{- else }} + - name: DATA_SOURCE_PASS + valueFrom: + secretKeyRef: + name: {{ include "postgresql.secretName" . }} + key: {{ include "postgresql.userPasswordKey" . }} + {{- end }} + - name: DATA_SOURCE_USER + value: {{ default "postgres" $customUser | quote }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.metrics.containerPorts.metrics }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.metrics.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.startupProbe "enabled") "context" $) | nindent 12 }} + tcpSocket: + port: http-metrics + {{- else if .Values.metrics.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customStartupProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.livenessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http-metrics + {{- else if .Values.metrics.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customLivenessProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.metrics.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.metrics.readinessProbe "enabled") "context" $) | nindent 12 }} + httpGet: + path: / + port: http-metrics + {{- else if .Values.metrics.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.customReadinessProbe "context" $) | nindent 12 }} + {{- end }} + {{- end }} + volumeMounts: + {{- if .Values.auth.usePasswordFiles }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.customMetrics }} + - name: custom-metrics + mountPath: /conf + readOnly: true + {{- end }} + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.readReplicas.sidecars }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.sidecars "context" $ ) | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.auth.usePasswordFiles }} + - name: postgresql-password + secret: + secretName: {{ include "postgresql.secretName" . }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + secret: + secretName: {{ include "postgresql.tlsSecretName" . }} + - name: postgresql-certificates + emptyDir: {} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} + - name: custom-metrics + configMap: + name: {{ printf "%s-metrics" (include "common.names.fullname" .) }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + emptyDir: + medium: Memory + {{- if .Values.shmVolume.sizeLimit }} + sizeLimit: {{ .Values.shmVolume.sizeLimit }} + {{- end }} + {{- end }} + {{- if .Values.readReplicas.extraVolumes }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.extraVolumes "context" $ ) | nindent 8 }} + {{- end }} + {{- if not .Values.readReplicas.persistence.enabled }} + - name: data + emptyDir: {} + {{- else }} + volumeClaimTemplates: + - metadata: + name: data + {{- if .Values.readReplicas.persistence.annotations }} + annotations: {{- toYaml .Values.readReplicas.persistence.annotations | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.readReplicas.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + {{- if .Values.readReplicas.persistence.dataSource }} + dataSource: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.persistence.dataSource "context" $) | nindent 10 }} + {{- end }} + resources: + requests: + storage: {{ .Values.readReplicas.persistence.size | quote }} + {{- if .Values.readReplicas.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.persistence.selector "context" $) | nindent 10 }} + {{- end -}} + {{- include "common.storage.class" (dict "persistence" .Values.readReplicas.persistence "global" .Values.global) | nindent 8 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/svc-headless.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/svc-headless.yaml new file mode 100644 index 00000000..0371e49d --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/svc-headless.yaml @@ -0,0 +1,33 @@ +{{- if eq .Values.architecture "replication" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postgresql.readReplica.svc.headless" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + app.kubernetes.io/component: read + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + # Use this annotation in addition to the actual publishNotReadyAddresses + # field below because the annotation will stop being respected soon but the + # field is broken in some versions of Kubernetes: + # https://github.com/kubernetes/kubernetes/issues/58662 + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" +spec: + type: ClusterIP + clusterIP: None + # We want all pods in the StatefulSet to have their addresses published for + # the sake of the other Postgresql pods even before they're ready, since they + # have to be able to talk to each other in order to become ready. + publishNotReadyAddresses: true + ports: + - name: tcp-postgresql + port: {{ include "postgresql.readReplica.service.port" . }} + targetPort: tcp-postgresql + selector: {{- include "common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: read +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/svc.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/svc.yaml new file mode 100644 index 00000000..3eece4db --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/svc.yaml @@ -0,0 +1,53 @@ +{{- if eq .Values.architecture "replication" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postgresql.readReplica.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + app.kubernetes.io/component: read + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.readReplicas.service.annotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.service.annotations "context" $) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.readReplicas.service.type }} + {{- if or (eq .Values.readReplicas.service.type "LoadBalancer") (eq .Values.readReplicas.service.type "NodePort") }} + externalTrafficPolicy: {{ .Values.readReplicas.service.externalTrafficPolicy | quote }} + {{- end }} + {{- if and (eq .Values.readReplicas.service.type "LoadBalancer") (not (empty .Values.readReplicas.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.readReplicas.service.loadBalancerSourceRanges }} + {{- end }} + {{- if and (eq .Values.readReplicas.service.type "LoadBalancer") (not (empty .Values.readReplicas.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.readReplicas.service.loadBalancerIP }} + {{- end }} + {{- if and .Values.readReplicas.service.clusterIP (eq .Values.readReplicas.service.type "ClusterIP") }} + clusterIP: {{ .Values.readReplicas.service.clusterIP }} + {{- end }} + {{- if .Values.readReplicas.service.sessionAffinity }} + sessionAffinity: {{ .Values.readReplicas.service.sessionAffinity }} + {{- end }} + {{- if .Values.readReplicas.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: tcp-postgresql + port: {{ include "postgresql.readReplica.service.port" . }} + targetPort: tcp-postgresql + {{- if and (or (eq .Values.readReplicas.service.type "NodePort") (eq .Values.readReplicas.service.type "LoadBalancer")) (not (empty .Values.readReplicas.service.nodePorts.postgresql)) }} + nodePort: {{ .Values.readReplicas.service.nodePorts.postgresql }} + {{- else if eq .Values.readReplicas.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.readReplicas.service.extraPorts }} + {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.service.extraPorts "context" $) | nindent 4 }} + {{- end }} + selector: {{- include "common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: read +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/role.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/role.yaml new file mode 100644 index 00000000..00f92223 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/role.yaml @@ -0,0 +1,31 @@ +{{- if .Values.rbac.create }} +kind: Role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +# yamllint disable rule:indentation +rules: + {{- $pspAvailable := (semverCompare "<1.25-0" (include "common.capabilities.kubeVersion" .)) -}} + {{- if and $pspAvailable .Values.psp.create }} + - apiGroups: + - 'policy' + resources: + - 'podsecuritypolicies' + verbs: + - 'use' + resourceNames: + - {{ include "common.names.fullname" . }} + {{- end }} + {{- if .Values.rbac.rules }} + {{- include "common.tplvalues.render" ( dict "value" .Values.rbac.rules "context" $ ) | nindent 2 }} + {{- end }} +# yamllint enable rule:indentation +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/rolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/rolebinding.yaml new file mode 100644 index 00000000..0311c0ec --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/rolebinding.yaml @@ -0,0 +1,22 @@ +{{- if .Values.rbac.create }} +kind: RoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +roleRef: + kind: Role + name: {{ include "common.names.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: {{ include "postgresql.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/secrets.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/secrets.yaml new file mode 100644 index 00000000..5f28fb37 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/secrets.yaml @@ -0,0 +1,29 @@ +{{- if (include "postgresql.createSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if .Values.auth.enablePostgresUser }} + postgres-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "postgres-password" "providedValues" (list "global.postgresql.auth.postgresPassword" "auth.postgresPassword") "context" $) }} + {{- end }} + {{- if not (empty (include "postgresql.username" .)) }} + password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "password" "providedValues" (list "global.postgresql.auth.password" "auth.password") "context" $) }} + {{- end }} + {{- if eq .Values.architecture "replication" }} + replication-password: {{ include "common.secrets.passwords.manage" (dict "secret" (include "common.names.fullname" .) "key" "replication-password" "providedValues" (list "auth.replicationPassword") "context" $) }} + {{- end }} + # We don't auto-generate LDAP password when it's not provided as we do for other passwords + {{- if and .Values.ldap.enabled (or .Values.ldap.bind_password .Values.ldap.bindpw) }} + ldap-password: {{ coalesce .Values.ldap.bind_password .Values.ldap.bindpw | b64enc | quote }} + {{- end }} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/serviceaccount.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/serviceaccount.yaml new file mode 100644 index 00000000..179f8f2e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "postgresql.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.serviceAccount.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.serviceAccount.annotations "context" $ ) | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/tls-secrets.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/tls-secrets.yaml new file mode 100644 index 00000000..59c57764 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/tls-secrets.yaml @@ -0,0 +1,27 @@ +{{- if (include "postgresql.createTlsSecret" . ) }} +{{- $ca := genCA "postgresql-ca" 365 }} +{{- $fullname := include "common.names.fullname" . }} +{{- $releaseNamespace := .Release.Namespace }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $primaryHeadlessServiceName := include "postgresql.primary.svc.headless" . }} +{{- $readHeadlessServiceName := include "postgresql.readReplica.svc.headless" . }} +{{- $altNames := list (printf "*.%s.%s.svc.%s" $fullname $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $fullname $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $primaryHeadlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $primaryHeadlessServiceName $releaseNamespace $clusterDomain) (printf "*.%s.%s.svc.%s" $readHeadlessServiceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc.%s" $readHeadlessServiceName $releaseNamespace $clusterDomain) $fullname }} +{{- $crt := genSignedCert $fullname nil $altNames 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-crt" (include "common.names.fullname" .) }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + ca.crt: {{ $ca.Cert | b64enc | quote }} + tls.crt: {{ $crt.Cert | b64enc | quote }} + tls.key: {{ $crt.Key | b64enc | quote }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/values.schema.json b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/values.schema.json new file mode 100644 index 00000000..fc41483c --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/values.schema.json @@ -0,0 +1,156 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "architecture": { + "type": "string", + "title": "PostgreSQL architecture", + "form": true, + "description": "Allowed values: `standalone` or `replication`" + }, + "auth": { + "type": "object", + "title": "Authentication configuration", + "form": true, + "properties": { + "enablePostgresUser": { + "type": "boolean", + "title": "Enable \"postgres\" admin user", + "description": "Assign a password to the \"postgres\" admin user. Otherwise, remote access will be blocked for this user", + "form": true + }, + "postgresPassword": { + "type": "string", + "title": "Password for the \"postgres\" admin user", + "description": "Defaults to a random 10-character alphanumeric string if not set", + "form": true + }, + "database": { + "type": "string", + "title": "PostgreSQL custom database", + "description": "Name of the custom database to be created during the 1st initialization of PostgreSQL", + "form": true + }, + "username": { + "type": "string", + "title": "PostgreSQL custom user", + "description": "Name of the custom user to be created during the 1st initialization of PostgreSQL. This user only has permissions on the PostgreSQL custom database", + "form": true + }, + "password": { + "type": "string", + "title": "Password for the custom user to create", + "description": "Defaults to a random 10-character alphanumeric string if not set", + "form": true + }, + "replicationUsername": { + "type": "string", + "title": "PostgreSQL replication user", + "description": "Name of user used to manage replication.", + "form": true, + "hidden": { + "value": "standalone", + "path": "architecture" + } + }, + "replicationPassword": { + "type": "string", + "title": "Password for PostgreSQL replication user", + "description": "Defaults to a random 10-character alphanumeric string if not set", + "form": true, + "hidden": { + "value": "standalone", + "path": "architecture" + } + } + } + }, + "persistence": { + "type": "object", + "properties": { + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi" + } + } + }, + "resources": { + "type": "object", + "title": "Required Resources", + "description": "Configure resource requests", + "form": true, + "properties": { + "requests": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "form": true, + "render": "slider", + "title": "Memory Request", + "sliderMin": 10, + "sliderMax": 2048, + "sliderUnit": "Mi" + }, + "cpu": { + "type": "string", + "form": true, + "render": "slider", + "title": "CPU Request", + "sliderMin": 10, + "sliderMax": 2000, + "sliderUnit": "m" + } + } + } + } + }, + "replication": { + "type": "object", + "form": true, + "title": "Replication Details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enable Replication", + "form": true + }, + "readReplicas": { + "type": "integer", + "title": "read Replicas", + "form": true, + "hidden": { + "value": "standalone", + "path": "architecture" + } + } + } + }, + "volumePermissions": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Init Containers", + "description": "Change the owner of the persist volume mountpoint to RunAsUser:fsGroup" + } + } + }, + "metrics": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Configure metrics exporter", + "form": true + } + } + } + } +} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/values.yaml new file mode 100644 index 00000000..0bddba63 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/values.yaml @@ -0,0 +1,1374 @@ +## @section Global parameters +## Please, note that this will override the parameters, including dependencies, configured to use the global value +## +global: + ## @param global.imageRegistry Global Docker image registry + ## + imageRegistry: "" + ## @param global.imagePullSecrets Global Docker registry secret names as an array + ## e.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + ## @param global.storageClass Global StorageClass for Persistent Volume(s) + ## + storageClass: "" + postgresql: + ## @param global.postgresql.auth.postgresPassword Password for the "postgres" admin user (overrides `auth.postgresPassword`) + ## @param global.postgresql.auth.username Name for a custom user to create (overrides `auth.username`) + ## @param global.postgresql.auth.password Password for the custom user to create (overrides `auth.password`) + ## @param global.postgresql.auth.database Name for a custom database to create (overrides `auth.database`) + ## @param global.postgresql.auth.existingSecret Name of existing secret to use for PostgreSQL credentials (overrides `auth.existingSecret`). + ## @param global.postgresql.auth.secretKeys.adminPasswordKey Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.adminPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. + ## @param global.postgresql.auth.secretKeys.userPasswordKey Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.userPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. + ## @param global.postgresql.auth.secretKeys.replicationPasswordKey Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.replicationPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set. + ## + auth: + postgresPassword: "" + username: "" + password: "" + database: "" + existingSecret: "" + secretKeys: + adminPasswordKey: "" + userPasswordKey: "" + replicationPasswordKey: "" + ## @param global.postgresql.service.ports.postgresql PostgreSQL service port (overrides `service.ports.postgresql`) + ## + service: + ports: + postgresql: "" + +## @section Common parameters +## + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param nameOverride String to partially override common.names.fullname template (will maintain the release name) +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname template +## +fullnameOverride: "" +## @param clusterDomain Kubernetes Cluster Domain +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release (evaluated as a template) +## +extraDeploy: [] +## @param commonLabels Add labels to all the deployed resources +## +commonLabels: {} +## @param commonAnnotations Add annotations to all the deployed resources +## +commonAnnotations: {} +## Enable diagnostic mode in the statefulset +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the statefulset + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the statefulset + ## + args: + - infinity + +## @section PostgreSQL common parameters +## + +## Bitnami PostgreSQL image version +## ref: https://hub.docker.com/r/bitnami/postgresql/tags/ +## @param image.registry PostgreSQL image registry +## @param image.repository PostgreSQL image repository +## @param image.tag PostgreSQL image tag (immutable tags are recommended) +## @param image.pullPolicy PostgreSQL image pull policy +## @param image.pullSecrets Specify image pull secrets +## @param image.debug Specify if debug values should be set +## +image: + registry: docker.io + repository: bitnami/postgresql + tag: 14.4.0-debian-11-r4 + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## + debug: false +## Authentication parameters +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-on-first-run +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-user-on-first-run +## +auth: + ## @param auth.enablePostgresUser Assign a password to the "postgres" admin user. Otherwise, remote access will be blocked for this user + ## + enablePostgresUser: true + ## @param auth.postgresPassword Password for the "postgres" admin user. Ignored if `auth.existingSecret` with key `postgres-password` is provided + ## + postgresPassword: "" + ## @param auth.username Name for a custom user to create + ## + username: "" + ## @param auth.password Password for the custom user to create. Ignored if `auth.existingSecret` with key `password` is provided + ## + password: "" + ## @param auth.database Name for a custom database to create + ## + database: "" + ## @param auth.replicationUsername Name of the replication user + ## + replicationUsername: repl_user + ## @param auth.replicationPassword Password for the replication user. Ignored if `auth.existingSecret` with key `replication-password` is provided + ## + replicationPassword: "" + ## @param auth.existingSecret Name of existing secret to use for PostgreSQL credentials. `auth.postgresPassword`, `auth.password`, and `auth.replicationPassword` will be ignored and picked up from this secret. The secret might also contains the key `ldap-password` if LDAP is enabled. `ldap.bind_password` will be ignored and picked from this secret in this case. + ## + existingSecret: "" + ## @param auth.secretKeys.adminPasswordKey Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. + ## @param auth.secretKeys.userPasswordKey Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. + ## @param auth.secretKeys.replicationPasswordKey Name of key in existing secret to use for PostgreSQL credentials. Only used when `auth.existingSecret` is set. + ## + secretKeys: + adminPasswordKey: postgres-password + userPasswordKey: password + replicationPasswordKey: replication-password + ## @param auth.usePasswordFiles Mount credentials as a files instead of using an environment variable + ## + usePasswordFiles: false +## @param architecture PostgreSQL architecture (`standalone` or `replication`) +## +architecture: standalone +## Replication configuration +## Ignored if `architecture` is `standalone` +## +replication: + ## @param replication.synchronousCommit Set synchronous commit mode. Allowed values: `on`, `remote_apply`, `remote_write`, `local` and `off` + ## @param replication.numSynchronousReplicas Number of replicas that will have synchronous replication. Note: Cannot be greater than `readReplicas.replicaCount`. + ## ref: https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-SYNCHRONOUS-COMMIT + ## + synchronousCommit: "off" + numSynchronousReplicas: 0 + ## @param replication.applicationName Cluster application name. Useful for advanced replication settings + ## + applicationName: my_application +## @param containerPorts.postgresql PostgreSQL container port +## +containerPorts: + postgresql: 5432 +## Audit settings +## https://github.com/bitnami/bitnami-docker-postgresql#auditing +## @param audit.logHostname Log client hostnames +## @param audit.logConnections Add client log-in operations to the log file +## @param audit.logDisconnections Add client log-outs operations to the log file +## @param audit.pgAuditLog Add operations to log using the pgAudit extension +## @param audit.pgAuditLogCatalog Log catalog using pgAudit +## @param audit.clientMinMessages Message log level to share with the user +## @param audit.logLinePrefix Template for log line prefix (default if not set) +## @param audit.logTimezone Timezone for the log timestamps +## +audit: + logHostname: false + logConnections: false + logDisconnections: false + pgAuditLog: "" + pgAuditLogCatalog: "off" + clientMinMessages: error + logLinePrefix: "" + logTimezone: "" +## LDAP configuration +## @param ldap.enabled Enable LDAP support +## DEPRECATED ldap.url It will removed in a future, please use 'ldap.uri' instead +## @param ldap.server IP address or name of the LDAP server. +## @param ldap.port Port number on the LDAP server to connect to +## @param ldap.prefix String to prepend to the user name when forming the DN to bind +## @param ldap.suffix String to append to the user name when forming the DN to bind +## DEPRECATED ldap.baseDN It will removed in a future, please use 'ldap.basedn' instead +## DEPRECATED ldap.bindDN It will removed in a future, please use 'ldap.binddn' instead +## DEPRECATED ldap.bind_password It will removed in a future, please use 'ldap.bindpw' instead +## @param ldap.basedn Root DN to begin the search for the user in +## @param ldap.binddn DN of user to bind to LDAP +## @param ldap.bindpw Password for the user to bind to LDAP +## DEPRECATED ldap.search_attr It will removed in a future, please use 'ldap.searchAttribute' instead +## DEPRECATED ldap.search_filter It will removed in a future, please use 'ldap.searchFilter' instead +## @param ldap.searchAttribute Attribute to match against the user name in the search +## @param ldap.searchFilter The search filter to use when doing search+bind authentication +## @param ldap.scheme Set to `ldaps` to use LDAPS +## DEPRECATED ldap.tls as string is deprecated,please use 'ldap.tls.enabled' instead +## @param ldap.tls.enabled Se to true to enable TLS encryption +## +ldap: + enabled: false + server: "" + port: "" + prefix: "" + suffix: "" + basedn: "" + binddn: "" + bindpw: "" + searchAttribute: "" + searchFilter: "" + scheme: "" + tls: + enabled: false + ## @param ldap.uri LDAP URL beginning in the form `ldap[s]://host[:port]/basedn`. If provided, all the other LDAP parameters will be ignored. + ## Ref: https://www.postgresql.org/docs/current/auth-ldap.html + uri: "" +## @param postgresqlDataDir PostgreSQL data dir folder +## +postgresqlDataDir: /bitnami/postgresql/data +## @param postgresqlSharedPreloadLibraries Shared preload libraries (comma-separated list) +## +postgresqlSharedPreloadLibraries: "pgaudit" +## Start PostgreSQL pod(s) without limitations on shm memory. +## By default docker and containerd (and possibly other container runtimes) limit `/dev/shm` to `64M` +## ref: https://github.com/docker-library/postgres/issues/416 +## ref: https://github.com/containerd/containerd/issues/3654 +## +shmVolume: + ## @param shmVolume.enabled Enable emptyDir volume for /dev/shm for PostgreSQL pod(s) + ## + enabled: true + ## @param shmVolume.sizeLimit Set this to enable a size limit on the shm tmpfs + ## Note: the size of the tmpfs counts against container's memory limit + ## e.g: + ## sizeLimit: 1Gi + ## + sizeLimit: "" +## TLS configuration +## +tls: + ## @param tls.enabled Enable TLS traffic support + ## + enabled: false + ## @param tls.autoGenerated Generate automatically self-signed TLS certificates + ## + autoGenerated: false + ## @param tls.preferServerCiphers Whether to use the server's TLS cipher preferences rather than the client's + ## + preferServerCiphers: true + ## @param tls.certificatesSecret Name of an existing secret that contains the certificates + ## + certificatesSecret: "" + ## @param tls.certFilename Certificate filename + ## + certFilename: "" + ## @param tls.certKeyFilename Certificate key filename + ## + certKeyFilename: "" + ## @param tls.certCAFilename CA Certificate filename + ## If provided, PostgreSQL will authenticate TLS/SSL clients by requesting them a certificate + ## ref: https://www.postgresql.org/docs/9.6/auth-methods.html + ## + certCAFilename: "" + ## @param tls.crlFilename File containing a Certificate Revocation List + ## + crlFilename: "" + +## @section PostgreSQL Primary parameters +## +primary: + ## @param primary.configuration PostgreSQL Primary main configuration to be injected as ConfigMap + ## ref: https://www.postgresql.org/docs/current/static/runtime-config.html + ## + configuration: "" + ## @param primary.pgHbaConfiguration PostgreSQL Primary client authentication configuration + ## ref: https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html + ## e.g:# + ## pgHbaConfiguration: |- + ## local all all trust + ## host all all localhost trust + ## host mydatabase mysuser 192.168.0.0/24 md5 + ## + pgHbaConfiguration: "" + ## @param primary.existingConfigmap Name of an existing ConfigMap with PostgreSQL Primary configuration + ## NOTE: `primary.configuration` and `primary.pgHbaConfiguration` will be ignored + ## + existingConfigmap: "" + ## @param primary.extendedConfiguration Extended PostgreSQL Primary configuration (appended to main or default configuration) + ## ref: https://github.com/bitnami/bitnami-docker-postgresql#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf + ## + extendedConfiguration: "" + ## @param primary.existingExtendedConfigmap Name of an existing ConfigMap with PostgreSQL Primary extended configuration + ## NOTE: `primary.extendedConfiguration` will be ignored + ## + existingExtendedConfigmap: "" + ## Initdb configuration + ## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#specifying-initdb-arguments + ## + initdb: + ## @param primary.initdb.args PostgreSQL initdb extra arguments + ## + args: "" + ## @param primary.initdb.postgresqlWalDir Specify a custom location for the PostgreSQL transaction log + ## + postgresqlWalDir: "" + ## @param primary.initdb.scripts Dictionary of initdb scripts + ## Specify dictionary of scripts to be run at first boot + ## e.g: + ## scripts: + ## my_init_script.sh: | + ## #!/bin/sh + ## echo "Do something." + ## + scripts: {} + ## @param primary.initdb.scriptsConfigMap ConfigMap with scripts to be run at first boot + ## NOTE: This will override `primary.initdb.scripts` + ## + scriptsConfigMap: "" + ## @param primary.initdb.scriptsSecret Secret with scripts to be run at first boot (in case it contains sensitive information) + ## NOTE: This can work along `primary.initdb.scripts` or `primary.initdb.scriptsConfigMap` + ## + scriptsSecret: "" + ## @param primary.initdb.user Specify the PostgreSQL username to execute the initdb scripts + ## + user: "" + ## @param primary.initdb.password Specify the PostgreSQL password to execute the initdb scripts + ## + password: "" + ## Configure current cluster's primary server to be the standby server in other cluster. + ## This will allow cross cluster replication and provide cross cluster high availability. + ## You will need to configure pgHbaConfiguration if you want to enable this feature with local cluster replication enabled. + ## @param primary.standby.enabled Whether to enable current cluster's primary as standby server of another cluster or not + ## @param primary.standby.primaryHost The Host of replication primary in the other cluster + ## @param primary.standby.primaryPort The Port of replication primary in the other cluster + ## + standby: + enabled: false + primaryHost: "" + primaryPort: "" + ## @param primary.extraEnvVars Array with extra environment variables to add to PostgreSQL Primary nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param primary.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for PostgreSQL Primary nodes + ## + extraEnvVarsCM: "" + ## @param primary.extraEnvVarsSecret Name of existing Secret containing extra env vars for PostgreSQL Primary nodes + ## + extraEnvVarsSecret: "" + ## @param primary.command Override default container command (useful when using custom images) + ## + command: [] + ## @param primary.args Override default container args (useful when using custom images) + ## + args: [] + ## Configure extra options for PostgreSQL Primary containers' liveness, readiness and startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes + ## @param primary.livenessProbe.enabled Enable livenessProbe on PostgreSQL Primary containers + ## @param primary.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param primary.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param primary.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param primary.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param primary.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param primary.readinessProbe.enabled Enable readinessProbe on PostgreSQL Primary containers + ## @param primary.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param primary.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param primary.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param primary.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param primary.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param primary.startupProbe.enabled Enable startupProbe on PostgreSQL Primary containers + ## @param primary.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param primary.startupProbe.periodSeconds Period seconds for startupProbe + ## @param primary.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param primary.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param primary.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 15 + successThreshold: 1 + ## @param primary.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param primary.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param primary.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param primary.lifecycleHooks for the PostgreSQL Primary container to automate configuration before or after startup + ## + lifecycleHooks: {} + ## PostgreSQL Primary resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param primary.resources.limits The resources limits for the PostgreSQL Primary containers + ## @param primary.resources.requests.memory The requested memory for the PostgreSQL Primary containers + ## @param primary.resources.requests.cpu The requested cpu for the PostgreSQL Primary containers + ## + resources: + limits: {} + requests: + memory: 256Mi + cpu: 250m + ## Pod Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param primary.podSecurityContext.enabled Enable security context + ## @param primary.podSecurityContext.fsGroup Group ID for the pod + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param primary.containerSecurityContext.enabled Enable container security context + ## @param primary.containerSecurityContext.runAsUser User ID for the container + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + ## @param primary.hostAliases PostgreSQL primary pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param primary.hostNetwork Specify if host network should be enabled for PostgreSQL pod (postgresql primary) + ## + hostNetwork: false + ## @param primary.hostIPC Specify if host IPC should be enabled for PostgreSQL pod (postgresql primary) + ## + hostIPC: false + ## @param primary.labels Map of labels to add to the statefulset (postgresql primary) + ## + labels: {} + ## @param primary.annotations Annotations for PostgreSQL primary pods + ## + annotations: {} + ## @param primary.podLabels Map of labels to add to the pods (postgresql primary) + ## + podLabels: {} + ## @param primary.podAnnotations Map of annotations to add to the pods (postgresql primary) + ## + podAnnotations: {} + ## @param primary.podAffinityPreset PostgreSQL primary pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param primary.podAntiAffinityPreset PostgreSQL primary pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## PostgreSQL Primary node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param primary.nodeAffinityPreset.type PostgreSQL primary node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param primary.nodeAffinityPreset.key PostgreSQL primary node label key to match Ignored if `primary.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param primary.nodeAffinityPreset.values PostgreSQL primary node label values to match. Ignored if `primary.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param primary.affinity Affinity for PostgreSQL primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: primary.podAffinityPreset, primary.podAntiAffinityPreset, and primary.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param primary.nodeSelector Node labels for PostgreSQL primary pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param primary.tolerations Tolerations for PostgreSQL primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param primary.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param primary.priorityClassName Priority Class to use for each pod (postgresql primary) + ## + priorityClassName: "" + ## @param primary.schedulerName Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param primary.terminationGracePeriodSeconds Seconds PostgreSQL primary pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param primary.updateStrategy.type PostgreSQL Primary statefulset strategy type + ## @param primary.updateStrategy.rollingUpdate PostgreSQL Primary statefulset rolling update configuration parameters + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + type: RollingUpdate + rollingUpdate: {} + ## @param primary.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the PostgreSQL Primary container(s) + ## + extraVolumeMounts: [] + ## @param primary.extraVolumes Optionally specify extra list of additional volumes for the PostgreSQL Primary pod(s) + ## + extraVolumes: [] + ## @param primary.sidecars Add additional sidecar containers to the PostgreSQL Primary pod(s) + ## For example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param primary.initContainers Add additional init containers to the PostgreSQL Primary pod(s) + ## Example + ## + ## initContainers: + ## - name: do-something + ## image: busybox + ## command: ['do', 'something'] + ## + initContainers: [] + ## @param primary.extraPodSpec Optionally specify extra PodSpec for the PostgreSQL Primary pod(s) + ## + extraPodSpec: {} + ## PostgreSQL Primary service configuration + ## + service: + ## @param primary.service.type Kubernetes Service type + ## + type: ClusterIP + ## @param primary.service.ports.postgresql PostgreSQL service port + ## + ports: + postgresql: 5432 + ## Node ports to expose + ## NOTE: choose port between <30000-32767> + ## @param primary.service.nodePorts.postgresql Node port for PostgreSQL + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + postgresql: "" + ## @param primary.service.clusterIP Static clusterIP or None for headless services + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param primary.service.annotations Annotations for PostgreSQL primary service + ## + annotations: {} + ## @param primary.service.loadBalancerIP Load balancer IP if service type is `LoadBalancer` + ## Set the LoadBalancer service type to internal only + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param primary.service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param primary.service.loadBalancerSourceRanges Addresses that are allowed when service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param primary.service.extraPorts Extra ports to expose in the PostgreSQL primary service + ## + extraPorts: [] + ## @param primary.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param primary.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## PostgreSQL Primary persistence configuration + ## + persistence: + ## @param primary.persistence.enabled Enable PostgreSQL Primary data persistence using PVC + ## + enabled: true + ## @param primary.persistence.existingClaim Name of an existing PVC to use + ## + existingClaim: "" + ## @param primary.persistence.mountPath The path the volume will be mounted at + ## Note: useful when using custom PostgreSQL images + ## + mountPath: /bitnami/postgresql + ## @param primary.persistence.subPath The subdirectory of the volume to mount to + ## Useful in dev environments and one PV for multiple services + ## + subPath: "" + ## @param primary.persistence.storageClass PVC Storage Class for PostgreSQL Primary data volume + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "" + ## @param primary.persistence.accessModes PVC Access Mode for PostgreSQL volume + ## + accessModes: + - ReadWriteOnce + ## @param primary.persistence.size PVC Storage Request for PostgreSQL volume + ## + size: 8Gi + ## @param primary.persistence.annotations Annotations for the PVC + ## + annotations: {} + ## @param primary.persistence.selector Selector to match an existing Persistent Volume (this value is evaluated as a template) + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param primary.persistence.dataSource Custom PVC data source + ## + dataSource: {} + +## @section PostgreSQL read only replica parameters +## +readReplicas: + ## @param readReplicas.replicaCount Number of PostgreSQL read only replicas + ## + replicaCount: 1 + ## @param readReplicas.extraEnvVars Array with extra environment variables to add to PostgreSQL read only nodes + ## e.g: + ## extraEnvVars: + ## - name: FOO + ## value: "bar" + ## + extraEnvVars: [] + ## @param readReplicas.extraEnvVarsCM Name of existing ConfigMap containing extra env vars for PostgreSQL read only nodes + ## + extraEnvVarsCM: "" + ## @param readReplicas.extraEnvVarsSecret Name of existing Secret containing extra env vars for PostgreSQL read only nodes + ## + extraEnvVarsSecret: "" + ## @param readReplicas.command Override default container command (useful when using custom images) + ## + command: [] + ## @param readReplicas.args Override default container args (useful when using custom images) + ## + args: [] + ## Configure extra options for PostgreSQL read only containers' liveness, readiness and startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes + ## @param readReplicas.livenessProbe.enabled Enable livenessProbe on PostgreSQL read only containers + ## @param readReplicas.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param readReplicas.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param readReplicas.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param readReplicas.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param readReplicas.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param readReplicas.readinessProbe.enabled Enable readinessProbe on PostgreSQL read only containers + ## @param readReplicas.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param readReplicas.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param readReplicas.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param readReplicas.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param readReplicas.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param readReplicas.startupProbe.enabled Enable startupProbe on PostgreSQL read only containers + ## @param readReplicas.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param readReplicas.startupProbe.periodSeconds Period seconds for startupProbe + ## @param readReplicas.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param readReplicas.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param readReplicas.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 15 + successThreshold: 1 + ## @param readReplicas.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param readReplicas.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param readReplicas.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param readReplicas.lifecycleHooks for the PostgreSQL read only container to automate configuration before or after startup + ## + lifecycleHooks: {} + ## PostgreSQL read only resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param readReplicas.resources.limits The resources limits for the PostgreSQL read only containers + ## @param readReplicas.resources.requests.memory The requested memory for the PostgreSQL read only containers + ## @param readReplicas.resources.requests.cpu The requested cpu for the PostgreSQL read only containers + ## + resources: + limits: {} + requests: + memory: 256Mi + cpu: 250m + ## Pod Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param readReplicas.podSecurityContext.enabled Enable security context + ## @param readReplicas.podSecurityContext.fsGroup Group ID for the pod + ## + podSecurityContext: + enabled: true + fsGroup: 1001 + ## Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## @param readReplicas.containerSecurityContext.enabled Enable container security context + ## @param readReplicas.containerSecurityContext.runAsUser User ID for the container + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + ## @param readReplicas.hostAliases PostgreSQL read only pods host aliases + ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ + ## + hostAliases: [] + ## @param readReplicas.hostNetwork Specify if host network should be enabled for PostgreSQL pod (PostgreSQL read only) + ## + hostNetwork: false + ## @param readReplicas.hostIPC Specify if host IPC should be enabled for PostgreSQL pod (postgresql primary) + ## + hostIPC: false + ## @param readReplicas.labels Map of labels to add to the statefulset (PostgreSQL read only) + ## + labels: {} + ## @param readReplicas.annotations Annotations for PostgreSQL read only pods + ## + annotations: {} + ## @param readReplicas.podLabels Map of labels to add to the pods (PostgreSQL read only) + ## + podLabels: {} + ## @param readReplicas.podAnnotations Map of annotations to add to the pods (PostgreSQL read only) + ## + podAnnotations: {} + ## @param readReplicas.podAffinityPreset PostgreSQL read only pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAffinityPreset: "" + ## @param readReplicas.podAntiAffinityPreset PostgreSQL read only pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## + podAntiAffinityPreset: soft + ## PostgreSQL read only node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## + nodeAffinityPreset: + ## @param readReplicas.nodeAffinityPreset.type PostgreSQL read only node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param readReplicas.nodeAffinityPreset.key PostgreSQL read only node label key to match Ignored if `primary.affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param readReplicas.nodeAffinityPreset.values PostgreSQL read only node label values to match. Ignored if `primary.affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + ## @param readReplicas.affinity Affinity for PostgreSQL read only pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: primary.podAffinityPreset, primary.podAntiAffinityPreset, and primary.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + ## @param readReplicas.nodeSelector Node labels for PostgreSQL read only pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + ## @param readReplicas.tolerations Tolerations for PostgreSQL read only pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + ## @param readReplicas.topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template + ## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods + ## + topologySpreadConstraints: [] + ## @param readReplicas.priorityClassName Priority Class to use for each pod (PostgreSQL read only) + ## + priorityClassName: "" + ## @param readReplicas.schedulerName Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + schedulerName: "" + ## @param readReplicas.terminationGracePeriodSeconds Seconds PostgreSQL read only pod needs to terminate gracefully + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods + ## + terminationGracePeriodSeconds: "" + ## @param readReplicas.updateStrategy.type PostgreSQL read only statefulset strategy type + ## @param readReplicas.updateStrategy.rollingUpdate PostgreSQL read only statefulset rolling update configuration parameters + ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + ## + updateStrategy: + type: RollingUpdate + rollingUpdate: {} + ## @param readReplicas.extraVolumeMounts Optionally specify extra list of additional volumeMounts for the PostgreSQL read only container(s) + ## + extraVolumeMounts: [] + ## @param readReplicas.extraVolumes Optionally specify extra list of additional volumes for the PostgreSQL read only pod(s) + ## + extraVolumes: [] + ## @param readReplicas.sidecars Add additional sidecar containers to the PostgreSQL read only pod(s) + ## For example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + ## @param readReplicas.initContainers Add additional init containers to the PostgreSQL read only pod(s) + ## Example + ## + ## initContainers: + ## - name: do-something + ## image: busybox + ## command: ['do', 'something'] + ## + initContainers: [] + ## @param readReplicas.extraPodSpec Optionally specify extra PodSpec for the PostgreSQL read only pod(s) + ## + extraPodSpec: {} + ## PostgreSQL read only service configuration + ## + service: + ## @param readReplicas.service.type Kubernetes Service type + ## + type: ClusterIP + ## @param readReplicas.service.ports.postgresql PostgreSQL service port + ## + ports: + postgresql: 5432 + ## Node ports to expose + ## NOTE: choose port between <30000-32767> + ## @param readReplicas.service.nodePorts.postgresql Node port for PostgreSQL + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + postgresql: "" + ## @param readReplicas.service.clusterIP Static clusterIP or None for headless services + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param readReplicas.service.annotations Annotations for PostgreSQL read only service + ## + annotations: {} + ## @param readReplicas.service.loadBalancerIP Load balancer IP if service type is `LoadBalancer` + ## Set the LoadBalancer service type to internal only + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param readReplicas.service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param readReplicas.service.loadBalancerSourceRanges Addresses that are allowed when service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param readReplicas.service.extraPorts Extra ports to expose in the PostgreSQL read only service + ## + extraPorts: [] + ## @param readReplicas.service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param readReplicas.service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + ## + sessionAffinityConfig: {} + ## PostgreSQL read only persistence configuration + ## + persistence: + ## @param readReplicas.persistence.enabled Enable PostgreSQL read only data persistence using PVC + ## + enabled: true + ## @param readReplicas.persistence.mountPath The path the volume will be mounted at + ## Note: useful when using custom PostgreSQL images + ## + mountPath: /bitnami/postgresql + ## @param readReplicas.persistence.subPath The subdirectory of the volume to mount to + ## Useful in dev environments and one PV for multiple services + ## + subPath: "" + ## @param readReplicas.persistence.storageClass PVC Storage Class for PostgreSQL read only data volume + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "" + ## @param readReplicas.persistence.accessModes PVC Access Mode for PostgreSQL volume + ## + accessModes: + - ReadWriteOnce + ## @param readReplicas.persistence.size PVC Storage Request for PostgreSQL volume + ## + size: 8Gi + ## @param readReplicas.persistence.annotations Annotations for the PVC + ## + annotations: {} + ## @param readReplicas.persistence.selector Selector to match an existing Persistent Volume (this value is evaluated as a template) + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + ## @param readReplicas.persistence.dataSource Custom PVC data source + ## + dataSource: {} + +## @section NetworkPolicy parameters + +## Add networkpolicies +## +networkPolicy: + ## @param networkPolicy.enabled Enable network policies + ## + enabled: false + ## @param networkPolicy.metrics.enabled Enable network policies for metrics (prometheus) + ## @param networkPolicy.metrics.namespaceSelector [object] Monitoring namespace selector labels. These labels will be used to identify the prometheus' namespace. + ## @param networkPolicy.metrics.podSelector [object] Monitoring pod selector labels. These labels will be used to identify the Prometheus pods. + ## + metrics: + enabled: false + ## e.g: + ## namespaceSelector: + ## label: monitoring + ## + namespaceSelector: {} + ## e.g: + ## podSelector: + ## label: monitoring + ## + podSelector: {} + ## Ingress Rules + ## + ingressRules: + ## @param networkPolicy.ingressRules.primaryAccessOnlyFrom.enabled Enable ingress rule that makes PostgreSQL primary node only accessible from a particular origin. + ## @param networkPolicy.ingressRules.primaryAccessOnlyFrom.namespaceSelector [object] Namespace selector label that is allowed to access the PostgreSQL primary node. This label will be used to identified the allowed namespace(s). + ## @param networkPolicy.ingressRules.primaryAccessOnlyFrom.podSelector [object] Pods selector label that is allowed to access the PostgreSQL primary node. This label will be used to identified the allowed pod(s). + ## @param networkPolicy.ingressRules.primaryAccessOnlyFrom.customRules [object] Custom network policy for the PostgreSQL primary node. + ## + primaryAccessOnlyFrom: + enabled: false + ## e.g: + ## namespaceSelector: + ## label: ingress + ## + namespaceSelector: {} + ## e.g: + ## podSelector: + ## label: access + ## + podSelector: {} + ## custom ingress rules + ## e.g: + ## customRules: + ## - from: + ## - namespaceSelector: + ## matchLabels: + ## label: example + customRules: {} + ## @param networkPolicy.ingressRules.readReplicasAccessOnlyFrom.enabled Enable ingress rule that makes PostgreSQL read-only nodes only accessible from a particular origin. + ## @param networkPolicy.ingressRules.readReplicasAccessOnlyFrom.namespaceSelector [object] Namespace selector label that is allowed to access the PostgreSQL read-only nodes. This label will be used to identified the allowed namespace(s). + ## @param networkPolicy.ingressRules.readReplicasAccessOnlyFrom.podSelector [object] Pods selector label that is allowed to access the PostgreSQL read-only nodes. This label will be used to identified the allowed pod(s). + ## @param networkPolicy.ingressRules.readReplicasAccessOnlyFrom.customRules [object] Custom network policy for the PostgreSQL read-only nodes. + ## + readReplicasAccessOnlyFrom: + enabled: false + ## e.g: + ## namespaceSelector: + ## label: ingress + ## + namespaceSelector: {} + ## e.g: + ## podSelector: + ## label: access + ## + podSelector: {} + ## custom ingress rules + ## e.g: + ## CustomRules: + ## - from: + ## - namespaceSelector: + ## matchLabels: + ## label: example + customRules: {} + ## @param networkPolicy.egressRules.denyConnectionsToExternal Enable egress rule that denies outgoing traffic outside the cluster, except for DNS (port 53). + ## @param networkPolicy.egressRules.customRules [object] Custom network policy rule + ## + egressRules: + # Deny connections to external. This is not compatible with an external database. + denyConnectionsToExternal: false + ## Additional custom egress rules + ## e.g: + ## customRules: + ## - to: + ## - namespaceSelector: + ## matchLabels: + ## label: example + customRules: {} + +## @section Volume Permissions parameters + +## Init containers parameters: +## volumePermissions: Change the owner and group of the persistent volume(s) mountpoint(s) to 'runAsUser:fsGroup' on each node +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner and group of the persistent volume + ## + enabled: false + ## @param volumePermissions.image.registry Init container volume-permissions image registry + ## @param volumePermissions.image.repository Init container volume-permissions image repository + ## @param volumePermissions.image.tag Init container volume-permissions image tag (immutable tags are recommended) + ## @param volumePermissions.image.pullPolicy Init container volume-permissions image pull policy + ## @param volumePermissions.image.pullSecrets Init container volume-permissions image pull secrets + ## + image: + registry: docker.io + repository: bitnami/bitnami-shell + tag: 11-debian-11-r9 + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param volumePermissions.resources.limits Init container volume-permissions resource limits + ## @param volumePermissions.resources.requests Init container volume-permissions resource requests + ## + resources: + limits: {} + requests: {} + ## Init container' Security Context + ## Note: the chown of the data folder is done to containerSecurityContext.runAsUser + ## and not the below volumePermissions.containerSecurityContext.runAsUser + ## @param volumePermissions.containerSecurityContext.runAsUser User ID for the init container + ## + containerSecurityContext: + runAsUser: 0 + +## @section Other Parameters + +## Service account for PostgreSQL to use. +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + ## @param serviceAccount.create Enable creation of ServiceAccount for PostgreSQL pod + ## + create: false + ## @param serviceAccount.name The name of the ServiceAccount to use. + ## If not set and create is true, a name is generated using the common.names.fullname template + ## + name: "" + ## @param serviceAccount.automountServiceAccountToken Allows auto mount of ServiceAccountToken on the serviceAccount created + ## Can be set to false if pods using this serviceAccount do not need to use K8s API + ## + automountServiceAccountToken: true + ## @param serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} +## Creates role for ServiceAccount +## @param rbac.create Create Role and RoleBinding (required for PSP to work) +## +rbac: + create: false + ## @param rbac.rules Custom RBAC rules to set + ## e.g: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] +## Pod Security Policy +## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## @param psp.create Whether to create a PodSecurityPolicy. WARNING: PodSecurityPolicy is deprecated in Kubernetes v1.21 or later, unavailable in v1.25 or later +## +psp: + create: false + +## @section Metrics Parameters + +metrics: + ## @param metrics.enabled Start a prometheus exporter + ## + enabled: false + ## @param metrics.image.registry PostgreSQL Prometheus Exporter image registry + ## @param metrics.image.repository PostgreSQL Prometheus Exporter image repository + ## @param metrics.image.tag PostgreSQL Prometheus Exporter image tag (immutable tags are recommended) + ## @param metrics.image.pullPolicy PostgreSQL Prometheus Exporter image pull policy + ## @param metrics.image.pullSecrets Specify image pull secrets + ## + image: + registry: docker.io + repository: bitnami/postgres-exporter + tag: 0.10.1-debian-11-r9 + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## @param metrics.customMetrics Define additional custom metrics + ## ref: https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file + ## customMetrics: + ## pg_database: + ## query: "SELECT d.datname AS name, CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT') THEN pg_catalog.pg_database_size(d.datname) ELSE 0 END AS size_bytes FROM pg_catalog.pg_database d where datname not in ('template0', 'template1', 'postgres')" + ## metrics: + ## - name: + ## usage: "LABEL" + ## description: "Name of the database" + ## - size_bytes: + ## usage: "GAUGE" + ## description: "Size of the database in bytes" + ## + customMetrics: {} + ## @param metrics.extraEnvVars Extra environment variables to add to PostgreSQL Prometheus exporter + ## see: https://github.com/wrouesnel/postgres_exporter#environment-variables + ## For example: + ## extraEnvVars: + ## - name: PG_EXPORTER_DISABLE_DEFAULT_METRICS + ## value: "true" + ## + extraEnvVars: [] + ## PostgreSQL Prometheus exporter containers' Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param metrics.containerSecurityContext.enabled Enable PostgreSQL Prometheus exporter containers' Security Context + ## @param metrics.containerSecurityContext.runAsUser Set PostgreSQL Prometheus exporter containers' Security Context runAsUser + ## @param metrics.containerSecurityContext.runAsNonRoot Set PostgreSQL Prometheus exporter containers' Security Context runAsNonRoot + ## + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + ## Configure extra options for PostgreSQL Prometheus exporter containers' liveness, readiness and startup probes + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes + ## @param metrics.livenessProbe.enabled Enable livenessProbe on PostgreSQL Prometheus exporter containers + ## @param metrics.livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + ## @param metrics.livenessProbe.periodSeconds Period seconds for livenessProbe + ## @param metrics.livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + ## @param metrics.livenessProbe.failureThreshold Failure threshold for livenessProbe + ## @param metrics.livenessProbe.successThreshold Success threshold for livenessProbe + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param metrics.readinessProbe.enabled Enable readinessProbe on PostgreSQL Prometheus exporter containers + ## @param metrics.readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + ## @param metrics.readinessProbe.periodSeconds Period seconds for readinessProbe + ## @param metrics.readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + ## @param metrics.readinessProbe.failureThreshold Failure threshold for readinessProbe + ## @param metrics.readinessProbe.successThreshold Success threshold for readinessProbe + ## + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + ## @param metrics.startupProbe.enabled Enable startupProbe on PostgreSQL Prometheus exporter containers + ## @param metrics.startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + ## @param metrics.startupProbe.periodSeconds Period seconds for startupProbe + ## @param metrics.startupProbe.timeoutSeconds Timeout seconds for startupProbe + ## @param metrics.startupProbe.failureThreshold Failure threshold for startupProbe + ## @param metrics.startupProbe.successThreshold Success threshold for startupProbe + ## + startupProbe: + enabled: false + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 15 + successThreshold: 1 + ## @param metrics.customLivenessProbe Custom livenessProbe that overrides the default one + ## + customLivenessProbe: {} + ## @param metrics.customReadinessProbe Custom readinessProbe that overrides the default one + ## + customReadinessProbe: {} + ## @param metrics.customStartupProbe Custom startupProbe that overrides the default one + ## + customStartupProbe: {} + ## @param metrics.containerPorts.metrics PostgreSQL Prometheus exporter metrics container port + ## + containerPorts: + metrics: 9187 + ## PostgreSQL Prometheus exporter resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param metrics.resources.limits The resources limits for the PostgreSQL Prometheus exporter container + ## @param metrics.resources.requests The requested resources for the PostgreSQL Prometheus exporter container + ## + resources: + limits: {} + requests: {} + ## Service configuration + ## + service: + ## @param metrics.service.ports.metrics PostgreSQL Prometheus Exporter service port + ## + ports: + metrics: 9187 + ## @param metrics.service.clusterIP Static clusterIP or None for headless services + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address + ## + clusterIP: "" + ## @param metrics.service.sessionAffinity Control where client requests go, to the same pod or round-robin + ## Values: ClientIP or None + ## ref: https://kubernetes.io/docs/user-guide/services/ + ## + sessionAffinity: None + ## @param metrics.service.annotations [object] Annotations for Prometheus to auto-discover the metrics endpoint + ## + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.service.ports.metrics }}" + ## Prometheus Operator ServiceMonitor configuration + ## + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor Resource for scraping metrics using Prometheus Operator + ## + enabled: false + ## @param metrics.serviceMonitor.namespace Namespace for the ServiceMonitor Resource (defaults to the Release Namespace) + ## + namespace: "" + ## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped. + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## + interval: "" + ## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended + ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint + ## + scrapeTimeout: "" + ## @param metrics.serviceMonitor.labels Additional labels that can be used so ServiceMonitor will be discovered by Prometheus + ## + labels: {} + ## @param metrics.serviceMonitor.selector Prometheus instance selector labels + ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration + ## + selector: {} + ## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping + ## + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion + ## + metricRelabelings: [] + ## @param metrics.serviceMonitor.honorLabels Specify honorLabels parameter to add the scrape endpoint + ## + honorLabels: false + ## @param metrics.serviceMonitor.jobLabel The name of the label on the target service to use as the job name in prometheus. + ## + jobLabel: "" + ## Custom PrometheusRule to be defined + ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + ## @param metrics.prometheusRule.enabled Create a PrometheusRule for Prometheus Operator + ## + enabled: false + ## @param metrics.prometheusRule.namespace Namespace for the PrometheusRule Resource (defaults to the Release Namespace) + ## + namespace: "" + ## @param metrics.prometheusRule.labels Additional labels that can be used so PrometheusRule will be discovered by Prometheus + ## + labels: {} + ## @param metrics.prometheusRule.rules PrometheusRule definitions + ## Make sure to constraint the rules to the current postgresql service. + ## rules: + ## - alert: HugeReplicationLag + ## expr: pg_replication_lag{service="{{ printf "%s-metrics" (include "common.names.fullname" .) }}"} / 3600 > 1 + ## for: 1m + ## labels: + ## severity: critical + ## annotations: + ## description: replication for {{ include "common.names.fullname" . }} PostgreSQL is lagging by {{ "{{ $value }}" }} hour(s). + ## summary: PostgreSQL replication is lagging by {{ "{{ $value }}" }} hour(s). + ## + rules: [] diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/_helpers.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/_helpers.tpl new file mode 100644 index 00000000..7c75d5de --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/_helpers.tpl @@ -0,0 +1,43 @@ +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "panoptica.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create the product name. +*/}} +{{- define "product.name" -}} +{{- default .Chart.Name .Values.global.productNameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the target Kubernetes version. +Ref https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_capabilities.tpl +*/}} +{{- define "panoptica.capabilities.kubeVersion" -}} +{{- default .Capabilities.KubeVersion.Version .Values.global.kubeVersionOverride -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "panoptica.capabilities.hpa.apiVersion" -}} +{{- if semverCompare "<1.23-0" (include "panoptica.capabilities.kubeVersion" .) -}} +{{- print "autoscaling/v2beta2" -}} +{{- else -}} +{{- print "autoscaling/v2" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for poddisruptionbudget. +*/}} +{{- define "panoptica.capabilities.pdb.apiVersion" -}} +{{- if semverCompare "<1.21-0" (include "panoptica.capabilities.kubeVersion" .) -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/_helpers.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/_helpers.tpl new file mode 100644 index 00000000..50d07167 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/_helpers.tpl @@ -0,0 +1,44 @@ +{{- define "apiclarity.name" -}} +{{- "apiclarity" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "apiclarity.fullname" -}} +{{- "apiclarity" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "apiclarity.labels" -}} +helm.sh/chart: {{ include "panoptica.chart" . }} +{{ include "apiclarity.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.global.extraLabels }} +{{ toYaml $.Values.global.extraLabels }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "apiclarity.selectorLabels" -}} +app.kubernetes.io/name: {{ include "apiclarity.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "apiclarity.serviceAccountName" -}} +{{- if .Values.apiclarity.serviceAccount.create }} +{{- default (include "apiclarity.fullname" .) .Values.apiclarity.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.apiclarity.serviceAccount.name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/clusterrole.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/clusterrole.yaml new file mode 100644 index 00000000..a7d9099e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/clusterrole.yaml @@ -0,0 +1,19 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "apiclarity.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["nodes", "services", "pods"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps"] + resources: ["replicasets", "daemonsets", "deployments"] + verbs: ["get", "list", "watch"] + - apiGroups: [ "batch" ] + resources: [ "jobs" ] + verbs: [ "create", "get", "delete" ] +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/clusterrolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/clusterrolebinding.yaml new file mode 100644 index 00000000..50353a86 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/clusterrolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "apiclarity.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "apiclarity.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "apiclarity.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/deployment.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/deployment.yaml new file mode 100644 index 00000000..c63d13df --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/deployment.yaml @@ -0,0 +1,165 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "apiclarity.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "apiclarity.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + {{- if and .Values.global.isConnectionEnforcementEnabled (not .Values.istio.global.alreadyInstalled) }} + annotations: + traffic.sidecar.istio.io/includeOutboundIPRanges: "" + traffic.sidecar.istio.io/includeInboundPorts: "9000" + proxy.istio.io/config: | + holdApplicationUntilProxyStarts: true + proxyMetadata: + ISTIO_META_DNS_CAPTURE: "false" + ISTIO_META_INSECURE_STACKDRIVER_ENDPOINT: "" + TLS_INTERCEPTION: "false" + {{- end }} + labels: + {{- include "apiclarity.selectorLabels" . | nindent 8 }} + {{- if and .Values.global.isConnectionEnforcementEnabled (not .Values.istio.global.alreadyInstalled) }} + sidecar.istio.io/inject: "true" + {{- end }} + spec: + {{- with .Values.apiclarity.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "apiclarity.serviceAccountName" . }} + initContainers: + - name: apiclarity-wait-for-db + image: "{{ index .Values "apiclarity-postgresql" "image" "registry" }}/{{ index .Values "apiclarity-postgresql" "image" "repository" }}:{{ index .Values "apiclarity-postgresql" "image" "tag" }}" + imagePullPolicy: {{ index .Values "apiclarity-postgresql" "image" "pullPolicy" }} + command: ['sh', '-c', 'until pg_isready -h {{ include "apiclarity.fullname" . }}-postgresql -p 5432 -U "postgres" -d "dbname={{ index .Values "apiclarity-postgresql" "auth" "database" }}"; + do echo waiting for database; sleep 2; done;'] + securityContext: + runAsUser: 1001 + resources: + limits: + cpu: 200m + memory: 1000Mi + requests: + cpu: 100m + memory: 200Mi + containers: + - name: apiclarity + image: "{{ default .Values.global.registry .Values.apiclarity.image.registry }}/{{ .Values.apiclarity.image.repository }}:{{ .Values.apiclarity.image.tag }}" + imagePullPolicy: {{ .Values.apiclarity.image.pullPolicy }} + args: + - run + - --log-level + - {{ .Values.apiclarity.logLevel }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + # space separated list of response headers to ignore when reconstructing the spec + - name: RESPONSE_HEADERS_TO_IGNORE + valueFrom: + configMapKeyRef: + name: '{{ include "apiclarity.fullname" . }}-headers-to-ignore-configmap' + key: response.headers + # space separated list of request headers to ignore when reconstructing the spec + - name: REQUEST_HEADERS_TO_IGNORE + valueFrom: + configMapKeyRef: + name: '{{ include "apiclarity.fullname" . }}-headers-to-ignore-configmap' + key: request.headers + - name: TRACE_SAMPLING_ENABLED + value: "true" + - name: DB_NAME + value: {{ index .Values "apiclarity-postgresql" "auth" "database" }} + - name: DB_HOST + value: "{{ include "apiclarity.fullname" . }}-postgresql" + - name: DB_PORT_NUMBER + value: "5432" + - name: DB_USER + value: "postgres" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: {{ index .Values "apiclarity-postgresql" "auth" "existingSecret" }} + key: postgres-password + - name: STATE_BACKUP_FILE_NAME + value: /apiclarity/state.gob + - name: ENABLE_TLS + value: "true" + - name: ROOT_CERT_FILE_PATH + value: /etc/root-ca/ca.crt + - name: TLS_SERVER_CERT_FILE_PATH + value: /etc/certs/server.crt + - name: TLS_SERVER_KEY_FILE_PATH + value: /etc/certs/server.key + - name: NOTIFICATION_BACKEND_PREFIX + value: {{ include "controller.fullname" . }}.{{ .Release.Namespace }}:8082 + - name: FUZZER_JOB_TEMPLATE_CONFIG_MAP_NAME + value: "{{ include "apiclarity.fullname" . }}-fuzzer-template" + - name: FUZZER_DEPLOYMENT_TYPE + value: "configmap" + - name: DIFFER_SEND_NOTIFICATION_INTERVAL_SEC + value: {{ .Values.global.sendTelemetriesIntervalSec | quote }} + readinessProbe: + httpGet: + path: /healthz/ready + port: 8081 + periodSeconds: 30 + failureThreshold: 5 + timeoutSeconds: 10 + livenessProbe: + httpGet: + path: /healthz/live + port: 8081 + initialDelaySeconds: 10 + periodSeconds: 30 + failureThreshold: 5 + timeoutSeconds: 10 + securityContext: + {{- toYaml .Values.apiclarity.securityContext | nindent 12 }} + resources: + {{- toYaml .Values.apiclarity.resources | nindent 12 }} + volumeMounts: + - name: apiclarity + mountPath: '/apiclarity' + - name: certs + mountPath: /etc/certs + readOnly: true + - name: root-ca + mountPath: /etc/root-ca + readOnly: true + volumes: + - name: apiclarity + persistentVolumeClaim: + claimName: {{ include "apiclarity.fullname" . }} + - name: certs + secret: + secretName: apiclarity-tls + - name: root-ca + configMap: + name: {{ include "product.name" . }}-root-ca.crt + {{- with .Values.apiclarity.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.apiclarity.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.apiclarity.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.apiclarity.podSecurityContext | nindent 8 }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/fuzzer-template-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/fuzzer-template-configmap.yaml new file mode 100644 index 00000000..4e66dde8 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/fuzzer-template-configmap.yaml @@ -0,0 +1,67 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "apiclarity.fullname" . }}-fuzzer-template + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +data: + config: |- + apiVersion: batch/v1 + kind: Job + metadata: + namespace: '{{ .Release.Namespace }}' + labels: +{{- toYaml .Values.apiclarity.fuzzer.labels | nindent 8 }} + spec: + backoffLimit: 0 + ttlSecondsAfterFinished: 300 + template: + metadata: + labels: + {{- toYaml .Values.apiclarity.fuzzer.labels | nindent 12 }} + spec: + restartPolicy: Never + volumes: + - name: tmp-volume + emptyDir: {} + - name: root-ca + configMap: + name: {{ include "product.name" . }}-root-ca.crt + containers: + - name: fuzzer + image: "{{ default .Values.global.registry .Values.apiclarity.fuzzer.image.registry }}/{{ .Values.apiclarity.fuzzer.image.repository }}:{{ .Values.apiclarity.fuzzer.image.tag }}" + imagePullPolicy: {{ .Values.apiclarity.fuzzer.image.pullPolicy }} + volumeMounts: + - mountPath: /tmp + name: tmp-volume + - name: root-ca + mountPath: /etc/root-ca + readOnly: true + env: + - name: PLATFORM_TYPE + value: "API_CLARITY" + - name: PLATFORM_HOST + value: https://{{ include "apiclarity.fullname" . }}.{{ .Release.Namespace }}:8443/api + - name: FUZZER + value: "scn-fuzzer,restler" + - name: RESTLER_ROOT_PATH + value: "/tmp" + - name: RESTLER_TOKEN_INJECTOR_PATH + value: "/app/" + - name: DEBUG + value: {{ .Values.apiclarity.fuzzer.debug | quote }} + securityContext: + {{- toYaml .Values.apiclarity.fuzzer.securityContext | nindent 14 }} + resources: + {{- toYaml .Values.apiclarity.fuzzer.resources | nindent 14 }} + {{- with .Values.apiclarity.fuzzer.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.apiclarity.fuzzer.affinity }} + affinity: + {{- toYaml . | nindent 12 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/headers-to-ignore-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/headers-to-ignore-configmap.yaml new file mode 100644 index 00000000..8c2c59ad --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/headers-to-ignore-configmap.yaml @@ -0,0 +1,117 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "apiclarity.fullname" . }}-headers-to-ignore-configmap + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +data: + request.headers: |- + x-forwarded-proto + x-request-id + x-b3-traceid + x-b3-sampled + x-b3-spanid + x-span-name + x-b3-parentspanid + A-IM + Accept + Accept-Charset + Accept-Encoding + Accept-Language + Accept-Datetime + Access-Control-Request-Method + Access-Control-Request-Headers + Authorization + Cache-Control + Connection + Content-Length + Content-Type + Cookie + Date + Expect + Forwarded + From + Host + If-Match + If-Modified-Since + If-None-Match + If-Range + If-Unmodified-Since + Max-Forwards + Origin + Pragma + Proxy-Authorization + Range + Referer + TE + User-Agent + Upgrade + Via + Warning + response.headers: |- + x-application-context + Access-Control-Allow-Credentials + Access-Control-Allow-Headers + Access-Control-Allow-Methods + Access-Control-Allow-Origin + Access-Control-Expose-Headers + Access-Control-Max-Age + Accept-Ranges + Age + Allow + Alternate-Protocol + Cache-Control + Client-Date + Client-Peer + Client-Response-Num + Connection + Content-Disposition + Content-Encoding + Content-Language + Content-Length + Content-Location + Content-MD5 + Content-Range + Content-Security-Policy + X-Content-Security-Policy + X-WebKit-CSP + Content-Security-Policy-Report-Only + Content-Type + Date + ETag + Expires + HTTP + Keep-Alive + Last-Modified + Link + Location + P3P + Pragma + Proxy-Authenticate + Proxy-Connection + Refresh + Retry-After + Server + Set-Cookie + Status + Strict-Transport-Security + Timing-Allow-Origin + Trailer + Transfer-Encoding + Upgrade + Vary + Via + Warning + WWW-Authenticate + X-Aspnet-Version + X-Content-Type-Options + X-Frame-Options + X-Permitted-Cross-Domain-Policies + X-Pingback + X-Powered-By + X-Robots-Tag + X-UA-Compatible + X-XSS-Protection +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/pvc.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/pvc.yaml new file mode 100644 index 00000000..a45876d7 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/pvc.yaml @@ -0,0 +1,22 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ include "apiclarity.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.apiclarity.persistence.accessMode | quote }} + resources: + requests: + storage: {{ .Values.apiclarity.persistence.size }} + {{- if .Values.apiclarity.persistence.storageClass }} + {{- if (eq "-" .Values.apiclarity.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.apiclarity.persistence.storageClass }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/role.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/role.yaml new file mode 100644 index 00000000..7142a364 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/role.yaml @@ -0,0 +1,18 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "apiclarity.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +rules: + # needed for trace sampling manger and fuzzer + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "create", "update", "delete"] + # needed for fuzzer + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/rolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/rolebinding.yaml new file mode 100644 index 00000000..73b05fc9 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "apiclarity.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "apiclarity.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "apiclarity.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/secret.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/secret.yaml new file mode 100644 index 00000000..613bafff --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/secret.yaml @@ -0,0 +1,11 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ index .Values "apiclarity-postgresql" "auth" "existingSecret" }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +data: + postgres-password: {{ .Values.controller.secret.sharedSecret | b64enc }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/service-lb.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/service-lb.yaml new file mode 100644 index 00000000..44c716dc --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/service-lb.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.global.isAPISecurityEnabled .Values.apiclarity.traceSource.external -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "apiclarity.fullname" . }}-external + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +spec: + type: LoadBalancer + ports: + - name: https-external + port: 10443 + protocol: TCP + targetPort: 10443 + selector: + {{- include "apiclarity.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/service.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/service.yaml new file mode 100644 index 00000000..d93d11b8 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/service.yaml @@ -0,0 +1,41 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "apiclarity.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} +spec: + ports: + - name: http-trace-server + port: 9000 + protocol: TCP + targetPort: 9000 + - name: https-trace-server + port: 9443 + protocol: TCP + targetPort: 9443 + - name: http-backend + port: 8080 + protocol: TCP + targetPort: 8080 + - name: https-backend + port: 8443 + protocol: TCP + targetPort: 8443 + - name: http-trace-sampling-manager-server + port: 9990 + protocol: TCP + targetPort: 9990 + - name: grpc-trace-sampling-manager-server + port: 9991 + protocol: TCP + targetPort: 9991 + - name: healthz + port: 8081 + protocol: TCP + targetPort: 8081 + selector: + {{- include "apiclarity.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/serviceaccount.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/serviceaccount.yaml new file mode 100644 index 00000000..5173cf4e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.global.isAPISecurityEnabled .Values.apiclarity.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "apiclarity.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "apiclarity.labels" . | nindent 4 }} + {{- with .Values.apiclarity.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/tls.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/tls.yaml new file mode 100644 index 00000000..23050eb0 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/tls.yaml @@ -0,0 +1,71 @@ +{{- if .Values.global.isAPISecurityEnabled -}} +{{- $caCert := "" }} +{{- $controllerServerCert := "" }} +{{- $controllerServerKey := "" }} +{{- $apiclarityServerCert := "" }} +{{- $apiclarityServerKey := "" }} +{{- $productName := include "product.name" . -}} +{{- $rootCAConfigName := print $productName "-root-ca.crt" -}} +{{- $rootCAConfig := (lookup "v1" "ConfigMap" .Release.Namespace $rootCAConfigName) }} +{{- $controllerName := include "controller.fullname" . -}} +{{- $controllerCertSecretName := print $controllerName "-tls" -}} +{{- $controllerCertSecret := (lookup "v1" "Secret" .Release.Namespace $controllerCertSecretName) }} +{{- $apiclarityCertSecret := (lookup "v1" "Secret" .Release.Namespace "apiclarity-tls") }} +{{- if and $rootCAConfig $controllerCertSecret $apiclarityCertSecret }} +{{- $caCert = get $rootCAConfig.data "ca.crt" -}} +{{- $controllerServerCert = get $controllerCertSecret.data "server.crt" -}} +{{- $controllerServerKey = get $controllerCertSecret.data "server.key" -}} +{{- $apiclarityServerCert = get $apiclarityCertSecret.data "server.crt" -}} +{{- $apiclarityServerKey = get $apiclarityCertSecret.data "server.key" -}} +{{- else }} +{{- $controllerCN := include "controller.fullname" . -}} +{{- $controllerExternalDNS := print $controllerCN "." .Release.Namespace -}} +{{- $controllerExternalDNSWithSVC := print $controllerExternalDNS ".svc" -}} +{{- $controllerExternalDNSFullFQDN := print $controllerExternalDNS ".svc.cluster.local" -}} +{{- $apiclarityCN := include "apiclarity.fullname" . -}} +{{- $apiclarityExternalDNS := print $apiclarityCN "." .Release.Namespace -}} +{{- $apiclarityExternalDNSWithSVC := print $apiclarityExternalDNS ".svc" -}} +{{- $apiclarityExternalDNSFullFQDN := print $apiclarityExternalDNS ".svc.cluster.local" -}} +{{- $ca := genCA "root-ca" 3650 -}} +{{- $controllerCert := genSignedCert $controllerCN (list "127.0.0.1") (list $controllerCN $controllerExternalDNS $controllerExternalDNSWithSVC $controllerExternalDNSFullFQDN ) 730 $ca -}} +{{- $apiclarityCert := genSignedCert $apiclarityCN (list "127.0.0.1") (list $apiclarityCN $apiclarityExternalDNS $apiclarityExternalDNSWithSVC $apiclarityExternalDNSFullFQDN ) 730 $ca -}} +{{- $caCert = $ca.Cert -}} +{{- $controllerServerCert = ($controllerCert.Cert | b64enc) -}} +{{- $controllerServerKey = ($controllerCert.Key | b64enc) -}} +{{- $apiclarityServerCert = ($apiclarityCert.Cert | b64enc) -}} +{{- $apiclarityServerKey = ($apiclarityCert.Key | b64enc) -}} +{{- end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "product.name" . }}-root-ca.crt + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +data: + ca.crt: | + {{- $caCert | nindent 4 }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "controller.fullname" . }}-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +data: + server.crt: {{ $controllerServerCert }} + server.key: {{ $controllerServerKey }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: apiclarity-tls + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +data: + server.crt: {{ $apiclarityServerCert }} + server.key: {{ $apiclarityServerKey }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/wasm-envoy-filter.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/wasm-envoy-filter.yaml new file mode 100644 index 00000000..e2175c44 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/wasm-envoy-filter.yaml @@ -0,0 +1,150 @@ +{{- if and .Values.global.isAPISecurityEnabled .Values.apiclarity.traceSource.istio -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: {{ include "product.name" . }}-filter + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + component: trace-analyzer +spec: + {{- if .Values.global.isContainerSecurityEnabled }} + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + {{- end }} + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: envoy.filters.network.http_connection_manager + subFilter: + name: envoy.filters.http.router + patch: + operation: INSERT_BEFORE + value: + name: envoy.filters.http.wasm + typedConfig: + '@type': type.googleapis.com/udpa.type.v1.TypedStruct + typeUrl: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + name: {{ include "product.name" . }}-outbound-filter + rootId: {{ include "product.name" . }}-outbound-filter + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"trace_sampling_enabled": "true"} + vmConfig: + code: + remote: + http_uri: + cluster: wasm_file_server + timeout: 10s + uri: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:8081/http-trace-filter.wasm" + sha256: {{ .Values.apiclarity.traceWasmFilterSHA256 }} + runtime: envoy.wasm.runtime.v8 + vmId: {{ include "product.name" . }}-outbound-filter + - applyTo: CLUSTER + match: + context: SIDECAR_OUTBOUND + patch: + operation: ADD + value: + connect_timeout: 1s + dns_lookup_family: V4_ONLY + dns_refresh_rate: 5s + load_assignment: + cluster_name: wasm_file_server + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: {{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + port_value: 8081 + name: wasm_file_server + type: LOGICAL_DNS + - applyTo: CLUSTER + match: + context: SIDECAR_OUTBOUND + patch: + operation: ADD + value: # cluster specification + name: trace_analyzer + type: LOGICAL_DNS + connect_timeout: 0.5s + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: trace_analyzer + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + protocol: TCP + address: {{ include "apiclarity.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + port_value: 9000 +{{- if and .Values.global.isConnectionEnforcementEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.9000_._.{{ include "apiclarity.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "apiclarity.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 +{{- end }} + - applyTo: CLUSTER + match: + context: SIDECAR_OUTBOUND + patch: + operation: ADD + value: # cluster specification + name: trace-sampling-manager + type: LOGICAL_DNS + connect_timeout: 0.5s + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: trace-sampling-manager + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + protocol: TCP + address: {{ include "apiclarity.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + port_value: 9990 +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/_helpers.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/_helpers.tpl new file mode 100644 index 00000000..e7faaeaf --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/_helpers.tpl @@ -0,0 +1,59 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "controller.name" -}} +{{- default .Chart.Name .Values.controller.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "controller.fullname" -}} +{{- if .Values.controller.fullnameOverride -}} +{{- .Values.controller.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.controller.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "controller.labels" -}} +helm.sh/chart: {{ include "panoptica.chart" . }} +{{ include "controller.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.global.extraLabels }} +{{ toYaml $.Values.global.extraLabels }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "controller.selectorLabels" -}} +app: {{ include "controller.name" . }} +app.kubernetes.io/name: {{ include "controller.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "controller.serviceAccountName" -}} +{{- if .Values.controller.serviceAccount.create }} +{{- default (include "controller.fullname" .) .Values.controller.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.controller.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/cis-docker-benchmark-template-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/cis-docker-benchmark-template-configmap.yaml new file mode 100644 index 00000000..91990419 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/cis-docker-benchmark-template-configmap.yaml @@ -0,0 +1,75 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: cis-docker-benchmark-template + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +data: + config: |- + apiVersion: batch/v1 + kind: Job + metadata: + namespace: {{ default .Release.Namespace .Values.imageAnalysis.jobDefaultNamespace }} + labels: + app: cis-docker-benchmark + sidecar.istio.io/inject: "false" + kuma.io/sidecar-injection: "disabled" + spec: + backoffLimit: 0 + activeDeadlineSeconds: 1200 + ttlSecondsAfterFinished: 30 + template: + metadata: + labels: + app: cis-docker-benchmark + sidecar.istio.io/inject: "false" + kuma.io/sidecar-injection: "disabled" + spec: + restartPolicy: Never + initContainers: + - name: ensure-forwarding-server + image: "{{ default .Values.global.registry .Values.busybox.image.registry }}/{{ .Values.busybox.image.repository }}:{{ .Values.busybox.image.tag }}" + imagePullPolicy: {{ .Values.busybox.image.pullPolicy }} + securityContext: + {{- toYaml .Values.busybox.securityContext | nindent 16 }} + args: + - /bin/sh + - -c + - > + set -x; + while [ 1 ]; do + nc {{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local 25235; + if [ $? -eq 0 ]; then + break; + fi + echo waiting for images analysis SBOM result forwarding server; sleep 5; + done; + containers: + - name: cis-docker-benchmark + image: {{ default .Values.global.registry .Values.imageAnalysis.cisDockerBenchmark.image.registry }}/{{ .Values.imageAnalysis.cisDockerBenchmark.image.repository }}:{{ .Values.imageAnalysis.cisDockerBenchmark.image.tag }} + env: + - name: RESULT_SERVICE_ADDR + value: {{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:25235 + args: + - scan + volumeMounts: + - mountPath: /tmp + name: tmp-volume + securityContext: + {{- toYaml .Values.imageAnalysis.cisDockerBenchmark.securityContext | nindent 16 }} + resources: + {{- toYaml .Values.imageAnalysis.cisDockerBenchmark.resources | nindent 16 }} + volumes: + - name: tmp-volume + emptyDir: {} + securityContext: + {{- toYaml .Values.imageAnalysis.cisDockerBenchmark.podSecurityContext | nindent 12 }} + {{- with .Values.imageAnalysis.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.imageAnalysis.tolerations }} + tolerations: + {{- toYaml . | nindent 12 }} + {{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/cluster-configuration-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/cluster-configuration-configmap.yaml new file mode 100644 index 00000000..f913e234 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/cluster-configuration-configmap.yaml @@ -0,0 +1,100 @@ +{{- if and .Values.global.isConnectionEnforcementEnabled (not .Values.global.isContainerSecurityEnabled) }} +{{- fail "Connection enforcement can only be enabled if K8s security is enabled!" }} +{{- end }} +{{- if and .Values.global.validateDeployerPolicy (not .Values.global.isContainerSecurityEnabled) }} +{{- fail "Deployer Policy enforcement can only be enabled if K8s security is enabled!" }} +{{- end }} +{{- if and .Values.global.k8sEventsEnabled (not .Values.global.isContainerSecurityEnabled) }} +{{- fail "K8s Events monitoring can only be enabled if K8s security is enabled!" }} +{{- end }} +{{- if and .Values.global.autoLabelEnabled (not .Values.global.isContainerSecurityEnabled) }} +{{- fail "Namespace auto-labeling can only be enabled if K8s security is enabled!" }} +{{- end }} +{{- if and .Values.global.isContainerSecurityEnable .Values.global.ciImageSignatureValidation .Values.global.ciImageValidation }} +{{- fail "Cluster cannot have both CI image validation and CI image signature validation enabled!" }} +{{- end }} +{{- if .Values.global.tokenInjectionEnabled}} +{{- if not .Values.global.isAPISecurityEnabled }} +{{- fail "Token injection cannot be enabled when API security is disabled!" }} +{{- end }} +{{- if not .Values.global.isContainerSecurityEnabled }} +{{- fail "Token injection cannot be enabled when K8s security is disabled!" }} +{{- end }} +{{- if not .Values.global.skipCrossChartsVerification}} +{{- $statefulset := (lookup "apps/v1" "StatefulSet" "securecn-vault" "vault") }} +{{- if not $statefulset }} +{{- fail "Token injection cannot be enabled when Panoptica vault chart is not deployed (missing vault statefulset in securecn-vault namespace), please first deploy the missing chart." }} +{{- end }} +{{- end }} +{{- end }} +{{- if .Values.global.isConnectionEnforcementEnabled }} +{{- if semverCompare ">1.19-0" .Values.istio.global.version }} +{{- .Values.istio.global.version | printf "Maximun supported istio version is 1.19.x while istio.global.version is set to %s" | fail }} +{{- end }} +{{- if not .Values.global.skipCrossChartsVerification}} +{{- if not .Values.istio.global.alreadyInstalled }} +{{- $istiodDeployment := (lookup "apps/v1" "Deployment" "istio-system" "istiod") }} +{{- if not $istiodDeployment }} +{{- fail "Connection enforcement cannot be enabled when Panoptica istio chart is not deployed (missing istiod deployment in istio-system namespace), please first deploy the missing chart." }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- if and .Values.istio.global.alreadyInstalled .Values.global.enableTlsInspection }} +{{- fail "TLS Inspection can't be enabled when using an upstream istio (istio.global.alreadyInstalled == true)" }} +{{- end }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: cluster-configuration + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +data: + config: |- + kubernetesSecurityEnabled: {{ .Values.global.isContainerSecurityEnabled }} + {{- if .Values.global.isContainerSecurityEnabled }} + enableConnectionsControl: {{ .Values.global.isConnectionEnforcementEnabled }} + validateDeployerPolicy: {{ .Values.global.validateDeployerPolicy }} + k8sEventsEnabled: {{ .Values.global.k8sEventsEnabled }} + cdValidation: {{ .Values.global.cdValidation }} + ciImageSignatureValidation: {{ .Values.global.ciImageSignatureValidation }} + ciImageValidation: {{ .Values.global.ciImageValidation }} + restrictRegistries: {{ .Values.global.restrictRegistries }} + tokenInjectionEnabled: {{ .Values.global.tokenInjectionEnabled }} + connectionFailPolicyAllow: {{ .Values.global.connectionFailPolicyAllow }} + environmentFailurePolicyAllow: {{ .Values.global.environmentFailurePolicyAllow }} + sshMonitorEnabled: {{ .Values.global.isSSHMonitorEnabled }} + {{- else }} + {{- /* If container security is disabled defaults values should be true (meaning fail-close is false) */}} + connectionFailPolicyAllow: true + environmentFailurePolicyAllow: true + {{- end }} + apiSecurityEnabled: {{ .Values.global.isAPISecurityEnabled }} + {{- if .Values.global.isAPISecurityEnabled }} + enableFuzzTests: {{ .Values.apiclarity.fuzzer.enabled }} + installEnvoyTracingSupport: {{ .Values.apiclarity.traceSource.istio }} + supportExternalTraceSource: {{ .Values.apiclarity.traceSource.external }} + {{- end }} + autoLabelEnabled: {{ .Values.global.autoLabelEnabled }} + httpsProxy: "{{ .Values.global.httpsProxy }}" + internalRegistry: "{{ .Values.global.registry }}" + isPersistent: {{ .Values.controller.persistence.enabled }} + minimalNumberOfControllerReplicas: {{ .Values.controller.autoscaling.minReplicas }} + {{- if and .Values.global.isContainerSecurityEnabled .Values.global.isConnectionEnforcementEnabled }} + preserveOriginalSourceIp: {{ .Values.global.preserveOriginalSourceIp }} + tlsInspectionEnabled: {{ .Values.global.enableTlsInspection }} + istioInstallationParameters: + isIstioAlreadyInstalled: {{ .Values.istio.global.alreadyInstalled }} + istioVersion: {{ .Values.istio.global.version }} + serviceDiscoveryIsolationEnabled: {{ .Values.istio.global.serviceDiscoveryIsolationEnabled }} + {{- $configmap := (lookup "v1" "ConfigMap" "istio-system" "cluster-configuration") }} + {{- if $configmap }} + {{- $config := get $configmap.data "config" }} + {{- $config | nindent 4 }} + {{- end }} + {{- end }} + imageAnalysisConfiguration: + sbomEnabled: {{ .Values.imageAnalysis.sbom.enabled }} + cisDockerBenchmarkEnabled: {{ .Values.imageAnalysis.cisDockerBenchmark.enabled }} + parallelScannersNumber: {{ .Values.imageAnalysis.parallelScanners }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/clusterrole.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/clusterrole.yaml new file mode 100644 index 00000000..7efbe3ca --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/clusterrole.yaml @@ -0,0 +1,90 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "controller.fullname" . }} + labels: + {{- include "controller.labels" . | nindent 4 }} +rules: + - apiGroups: ["", "apps", "extensions", "batch", "rbac.authorization.k8s.io"] + resources: ["pods", "namespaces", "replicasets", "deployments", "jobs", "cronjobs", "daemonsets", "statefulsets", "nodes", "clusterroles", "clusterrolebindings", "roles", "rolebindings"] + verbs: ["get", "list", "watch"] +{{- if .Values.global.isContainerSecurityEnabled }} + # external service monitor + - apiGroups: ["", "networking.k8s.io", "networking.istio.io"] + resources: ["services", "endpoints", "ingresses", "virtualservices"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "update", "create"] + - apiGroups: [""] + resources: ["services"] + verbs: ["patch"] + - apiGroups: [""] + resources: ["pods/log"] + verbs: ["get"] + - apiGroups: [""] + resources: ["pods/exec"] + verbs: ["create"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list", "create", "update", "delete"] + - apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["create", "delete"] +{{- if .Values.global.isConnectionEnforcementEnabled }} + - apiGroups: ["networking.istio.io"] + resources: ["destinationrules", "serviceentries", "virtualservices", "envoyfilters"] + verbs: ["create", "patch", "get", "list", "delete"] + - apiGroups: ["security.istio.io"] + resources: ["peerauthentications"] + verbs: ["create", "patch", "list", "delete"] +{{- end }} + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["get", "patch", "create", "delete", "list", "watch"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: ["get", "patch", "create", "delete", "list", "watch"] +{{- if .Values.global.isExternalCaEnabled }} + # CSR signer + - apiGroups: ["certificates.k8s.io"] + resources: ["certificatesigningrequests"] + verbs: ["get", "list", "watch"] + - apiGroups: ["certificates.k8s.io"] + resources: ["certificatesigningrequests/status"] + verbs: ["update"] + - apiGroups: ["certificates.k8s.io"] + resources: ["signers"] + resourceNames: ["{{ include "product.name" . }}.io/*"] # all signers in the '{{ include "product.name" . }}.io' domain + verbs: ["sign"] + - apiGroups: ["cert-manager.io"] + resources: ["certificaterequests", "certificaterequests/status"] + verbs: ["get", "list", "watch", "create", "delete"] +{{- end }} +{{- if .Values.global.isOpenShift }} + - apiGroups: ["rbac.authorization.k8s.io"] + resources: ["clusterroles", "clusterrolebindings"] + verbs: ["get", "create", "update", "delete"] + - apiGroups: ["k8s.cni.cncf.io"] + resources: ["network-attachment-definitions"] + verbs: ["get", "create", "update", "delete"] +{{- end }} + # Allow bank-vaults to extract command metadata from an image. + - apiGroups: [""] + resources: ["serviceaccounts"] + verbs: ["get", "list"] +{{- else if .Values.global.isAPISecurityEnabled }} + # Get kube-system namespace uid + # Watch namespaces for protected services discovery + - apiGroups: [""] + resources: ["namespaces"] + verbs: ["get", "list", "watch"] + # Watch nodes for nodes info report + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] + # Watch services for protected services discovery + - apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "watch"] +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/clusterrolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/clusterrolebinding.yaml new file mode 100644 index 00000000..95d46c1d --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/clusterrolebinding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "controller.fullname" . }} + labels: + {{- include "controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "controller.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/deployment.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/deployment.yaml new file mode 100644 index 00000000..bef34b4e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/deployment.yaml @@ -0,0 +1,265 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +spec: + {{- if not .Values.controller.autoscaling.enabled }} + replicas: {{ .Values.controller.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "controller.selectorLabels" . | nindent 6 }} + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + template: + metadata: + annotations: + checksum/image-analysis-template-config: {{ include (print $.Template.BasePath "/controller/image-analysis-template-configmap.yaml") . | sha256sum }} + checksum/k8s-cis-benchmark-template-config: {{ include (print $.Template.BasePath "/controller/k8s-cis-benchmark-template-configmap.yaml") . | sha256sum }} + {{- if and .Values.global.isAPISecurityEnabled .Values.global.isConnectionEnforcementEnabled (not .Values.istio.global.alreadyInstalled) }} + traffic.sidecar.istio.io/includeOutboundIPRanges: "" + traffic.sidecar.istio.io/includeInboundPorts: "24229,24226" + proxy.istio.io/config: | + holdApplicationUntilProxyStarts: true + proxyMetadata: + ISTIO_META_DNS_CAPTURE: "false" + ISTIO_META_INSECURE_STACKDRIVER_ENDPOINT: "" + TLS_INTERCEPTION: "false" + {{- end }} + labels: + {{- include "controller.selectorLabels" . | nindent 8 }} + {{- if and .Values.global.isAPISecurityEnabled .Values.global.isConnectionEnforcementEnabled (not .Values.istio.global.alreadyInstalled) }} + sidecar.istio.io/inject: "true" + {{- end }} + spec: + {{- with .Values.controller.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "controller.serviceAccountName" . }} + initContainers: + {{- if .Values.global.isAPISecurityEnabled }} + - name: init-apiclarity + image: "{{ default .Values.global.registry .Values.busybox.image.registry }}/{{ .Values.busybox.image.repository }}:{{ .Values.busybox.image.tag }}" + imagePullPolicy: {{ .Values.busybox.image.pullPolicy }} + securityContext: + {{- toYaml .Values.busybox.securityContext | nindent 12 }} + args: + - /bin/sh + - -c + - > + set -x; + while [ $(curl -sw '%{http_code}' "http://{{ include "apiclarity.fullname" . }}.{{ .Release.Namespace }}:8081/healthz/ready" -o /dev/null) -ne 200 ]; do + echo waiting for apiclarity; sleep 2; + done; + {{- end }} + containers: + - name: {{ include "controller.fullname" . }} + image: "{{ default .Values.global.registry .Values.controller.image.registry }}/{{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag }}" + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + securityContext: + {{- toYaml .Values.controller.securityContext | nindent 12 }} + args: + - run + - --log-level + - {{ .Values.controller.logLevel }} + env: + - name: AGENT_ID + value: {{ required "Agent ID is required!" .Values.controller.agentID | quote }} + - name: MANAGEMENT_HOST + value: {{ .Values.global.mgmtHostname | quote }} + - name: SEND_TELEMETRIES_INTERVAL_SEC + value: {{ .Values.global.sendTelemetriesIntervalSec | quote }} + {{- if .Values.global.validateDeployerPolicy }} + - name: ENABLE_DEPLOYER_POLICY + value: "true" + {{- end }} + {{- if .Values.global.k8sEventsEnabled }} + - name: ENABLE_K8S_EVENTS + value: "true" + {{- end }} + {{- if .Values.controller.persistence.enabled }} + - name: AGENT_PERSISTENT_PATH + value: "/{{ include "controller.fullname" . }}" + - name: IS_PERSISTENT + value: "true" + {{- end }} + {{- if .Values.global.autoLabelEnabled }} + - name: ENABLE_NAMESPACE_AUTO_LABEL + value: "true" + {{- end }} + {{- if and .Values.global.tokenInjectionEnabled .Values.global.isContainerSecurityEnabled }} + - name: API_TOKEN_INJECTION_ENABLED + value: "true" + - name: VAULT_ENV_IMAGE + value: {{ default .Values.global.registry .Values.vaultEnv.image.registry }}/{{ .Values.vaultEnv.image.repository }}:{{ .Values.vaultEnv.image.tag }} + - name: VAULT_ENV_LOG_SERVER + value: {{ include "controller.fullname" . }}.{{ .Release.Namespace }}:9514 + {{- end }} + {{- if .Values.global.isOpenShift }} + - name: IS_OPENSHIFT + value: "true" + {{- end }} + - name: CONNECTION_EVENT_FORWARDING_SERVICE_ADDRESS + value: {{ include "controller.fullname" . }}.{{ .Release.Namespace }}:24234 + - name: CIS_BENCHMARK_CONFIG_MAP_NAMESPACE + value: {{ .Release.Namespace }} + - name: POD_NAMESPACE + value: {{ .Release.Namespace }} + - name: DEPLOYMENT_NAME + value: {{ include "controller.fullname" . }} + - name: SERVICE_NAME + value: {{ include "controller.fullname" . }} + - name: SA_NAME + value: {{ include "controller.serviceAccountName" . }} + - name: PRODUCT_NAME + value: {{ include "product.name" . }} + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_TEMPLATE_HASH + valueFrom: + fieldRef: + fieldPath: metadata.labels['pod-template-hash'] + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: SHARED_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.controller.secret.existingSecret | default (include "controller.fullname" .) }} + key: {{ .Values.controller.secret.sharedSecretKey | default "SHARED_SECRET" }} + - name: CONNECTION_FAILURE_POLICY_ALLOW + value: {{ .Values.global.connectionFailPolicyAllow | quote }} + - name: VALIDATING_FAILURE_POLICY_ALLOW + value: {{ .Values.global.environmentFailurePolicyAllow | quote }} + {{- if not .Values.global.enableTlsInspection }} + - name: DISABLE_TLS_INTERCEPTION + value: "true" + {{- end }} + {{- if .Values.global.isAPISecurityEnabled }} + - name: TRACE_SUPPORT_ENABLED + value: "true" + - name: TRACE_WASM_FILTER_SHA256 + value: {{ .Values.apiclarity.traceWasmFilterSHA256 }} + - name: APICLARITY_BACKEND_ADDRESS + value: {{ include "apiclarity.fullname" . }}.{{ .Release.Namespace }}:8443 + - name: TRACE_SAMPLING_MANAGER_GRPC_ADDRESS + value: {{ include "apiclarity.fullname" . }}.{{ .Release.Namespace }}:9991 + {{- if .Values.apiclarity.traceSource.external }} + - name: SUPPORT_EXTERNAL_TRACE_SOURCE + value: "true" + - name: APICLARITY_EXPOSED_SERVICE_NAME + value: "{{ include "apiclarity.fullname" . }}-external" + {{- end }} + {{- end }} + - name: K8S_CIS_BENCHMARK_ENABLED + value: {{ .Values.global.k8sCisBenchmarkEnabled | quote }} + - name: CONTAINER_SECURITY_ENABLED + value: {{ .Values.global.isContainerSecurityEnabled | quote }} + - name: SSH_MONITOR_ENABLED + value: {{ .Values.global.isSSHMonitorEnabled | quote }} + {{- if not .Values.global.isConnectionEnforcementEnabled }} + - name: CONNECTION_ENFORCEMENT + value: "Disabled" + {{- end }} + {{- if .Values.global.dummyPlaceHolderForTest }} + - name: AGENT_VERSION_FOR_TEST + value: 1.1.1 + {{- end }} + {{- if .Values.global.httpsProxy }} + - name: https_proxy + value: "{{ .Values.global.httpsProxy }}" + {{- end }} + {{- if .Values.global.httpProxy }} + - name: http_proxy + value: "{{ .Values.global.httpProxy }}" + {{- end }} + - name: IS_ISTIO_ALREADY_INSTALLED + value: {{ .Values.istio.global.alreadyInstalled | quote }} + {{- if .Values.global.isExternalCaEnabled }} + - name: EXTERNAL_CA_SIGNER_NAME + value: "{{ include "product.name" . }}.io/signer" + {{- end }} + - name: ETI_GCR_REPO + value: {{ .Values.global.registry | quote }} + - name: FUZZER_IMAGE_REPO + value: "{{ default .Values.global.registry .Values.apiclarity.fuzzer.image.registry }}/{{ .Values.apiclarity.fuzzer.image.repository }}" + - name: IS_MANAGED_BY_HELM + value: {{ .Values.global.isManagedByHelm | quote }} + resources: + {{- toYaml .Values.controller.resources | nindent 12 }} + readinessProbe: + httpGet: + path: /healthz/ready + port: 8080 + periodSeconds: 30 + failureThreshold: 5 + timeoutSeconds: 10 + livenessProbe: + httpGet: + path: /healthz/live + port: 8080 + initialDelaySeconds: 120 + periodSeconds: 30 + failureThreshold: 5 + timeoutSeconds: 10 + volumeMounts: + {{- if .Values.global.isAPISecurityEnabled }} + - mountPath: /etc/certs + name: certs + readOnly: true + - mountPath: /etc/root-ca + name: root-ca + readOnly: true + {{- end }} + {{- if not .Values.controller.persistence.enabled }} + - mountPath: /tmp + name: tmp-volume + {{- else }} + - name: {{ include "controller.fullname" . }} + mountPath: /{{ include "controller.fullname" . }} + {{- end }} + volumes: + {{- if .Values.global.isAPISecurityEnabled }} + - name: certs + secret: + secretName: {{ include "controller.fullname" . }}-tls + - name: root-ca + configMap: + name: {{ include "product.name" . }}-root-ca.crt + {{- end }} + {{- if not .Values.controller.persistence.enabled }} + - name: tmp-volume + emptyDir: {} + {{- else }} + - name: {{ include "controller.fullname" . }} + persistentVolumeClaim: + {{- if .Values.global.dummyPlaceHolderForTest }} + claimName: {{ include "product.name" . }}-pvc-for-test + {{- else }} + claimName: {{ include "product.name" . }}-{{ .Values.controller.persistence.pvcSuffix }} + {{- end }} + {{- end }} + {{- with .Values.controller.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.controller.podSecurityContext | nindent 8 }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/hpa.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/hpa.yaml new file mode 100644 index 00000000..85dfad81 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/hpa.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.controller.autoscaling.enabled (not .Values.controller.persistence.enabled) -}} +apiVersion: {{ include "panoptica.capabilities.hpa.apiVersion" . }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "controller.fullname" . }} + minReplicas: {{ .Values.controller.autoscaling.minReplicas }} + maxReplicas: {{ .Values.controller.autoscaling.maxReplicas }} + metrics: + {{- if .Values.controller.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.controller.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.controller.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.controller.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-clusterrole.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-clusterrole.yaml new file mode 100644 index 00000000..ea32b78b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-clusterrole.yaml @@ -0,0 +1,18 @@ +# ClusterRole to allow the Panoptica controller to perform image analysis. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "controller.fullname" . }}-image-analysis + labels: + {{- include "controller.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: + - "pods" + - "configmaps" + verbs: ["get", "list"] + + - apiGroups: ["batch"] + resources: + - "jobs" + verbs: ["create"] diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-clusterrolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-clusterrolebinding.yaml new file mode 100644 index 00000000..566a6a54 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-clusterrolebinding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "controller.fullname" . }}-image-analysis + labels: + {{- include "controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "controller.fullname" . }}-image-analysis +subjects: + - kind: ServiceAccount + name: {{ include "controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-template-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-template-configmap.yaml new file mode 100644 index 00000000..19af8c07 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-template-configmap.yaml @@ -0,0 +1,93 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: image-analysis-template + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +data: + config: |- + apiVersion: batch/v1 + kind: Job + metadata: + namespace: {{ default .Release.Namespace .Values.imageAnalysis.jobDefaultNamespace }} + labels: + app: image-analysis + sidecar.istio.io/inject: "false" + kuma.io/sidecar-injection: "disabled" + spec: + backoffLimit: 0 + activeDeadlineSeconds: 1200 + ttlSecondsAfterFinished: 30 + template: + metadata: + labels: + app: image-analysis + sidecar.istio.io/inject: "false" + kuma.io/sidecar-injection: "disabled" + spec: + restartPolicy: Never + initContainers: + - name: ensure-forwarding-server + image: "{{ default .Values.global.registry .Values.busybox.image.registry }}/{{ .Values.busybox.image.repository }}:{{ .Values.busybox.image.tag }}" + imagePullPolicy: {{ .Values.busybox.image.pullPolicy }} + securityContext: + {{- toYaml .Values.busybox.securityContext | nindent 16 }} + args: + - /bin/sh + - -c + - > + set -x; + while [ 1 ]; do + nc {{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local 25235; + if [ $? -eq 0 ]; then + break; + fi + echo waiting for images analysis SBOM result forwarding server; sleep 5; + done; + containers: + - name: image-analysis + image: "{{ default .Values.global.registry .Values.imageAnalysis.sbom.image.registry }}/{{ .Values.imageAnalysis.sbom.image.repository }}:{{ .Values.imageAnalysis.sbom.image.tag }}" + env: + - name: ANALYZER_LIST + value: "syft" + - name: RESULT_SERVICE_ADDR + value: {{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:25235 + - name: REGISTRY_SKIP_VERIFY_TLS + value: {{ .Values.imageAnalysis.registry.skipVerifyTlS | quote }} + - name: REGISTRY_USE_HTTP + value: {{ .Values.imageAnalysis.registry.useHTTP | quote }} + {{- if .Values.global.httpsProxy }} + - name: HTTPS_PROXY + value: "{{ .Values.global.httpsProxy }}" + {{- end }} + {{- if .Values.global.httpProxy }} + - name: HTTP_PROXY + value: "{{ .Values.global.httpProxy }}" + {{- end }} + {{- if or .Values.global.httpProxy .Values.global.httpsProxy }} + - name: NO_PROXY + value: {{ include "controller.fullname" . }}.{{ .Release.Namespace }}:25235 + {{- end }} + args: + - analyze + volumeMounts: + - mountPath: /tmp + name: tmp-volume + securityContext: + {{- toYaml .Values.imageAnalysis.sbom.securityContext | nindent 16 }} + resources: + {{- toYaml .Values.imageAnalysis.sbom.resources | nindent 16 }} + volumes: + - name: tmp-volume + emptyDir: {} + securityContext: + {{- toYaml .Values.imageAnalysis.sbom.podSecurityContext | nindent 12 }} + {{- with .Values.imageAnalysis.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.imageAnalysis.tolerations }} + tolerations: + {{- toYaml . | nindent 12 }} + {{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-clusterrole.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-clusterrole.yaml new file mode 100644 index 00000000..33e8945c --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-clusterrole.yaml @@ -0,0 +1,13 @@ +{{- if .Values.global.k8sCisBenchmarkEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "controller.fullname" . }}-k8s-cis-benchmark + labels: + {{- include "controller.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: + - "nodes" + verbs: ["get", "list"] +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-clusterrolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-clusterrolebinding.yaml new file mode 100644 index 00000000..a09520f2 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if .Values.global.k8sCisBenchmarkEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "controller.fullname" . }}-k8s-cis-benchmark + labels: + {{- include "controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "controller.fullname" . }}-k8s-cis-benchmark +subjects: + - kind: ServiceAccount + name: {{ include "controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-role.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-role.yaml new file mode 100644 index 00000000..b95d201b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-role.yaml @@ -0,0 +1,19 @@ +{{- if .Values.global.k8sCisBenchmarkEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "controller.fullname" . }}-k8s-cis-benchmark + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: + - "configmaps" + verbs: ["get", "list"] + + - apiGroups: ["batch"] + resources: + - "jobs" + verbs: ["create", "get", "list"] +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-rolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-rolebinding.yaml new file mode 100644 index 00000000..2f92fbb1 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.global.k8sCisBenchmarkEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "controller.fullname" . }}-k8s-cis-benchmark + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "controller.fullname" . }}-k8s-cis-benchmark +subjects: + - kind: ServiceAccount + name: {{ include "controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-template-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-template-configmap.yaml new file mode 100644 index 00000000..401eb684 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-template-configmap.yaml @@ -0,0 +1,80 @@ +{{- if .Values.global.k8sCisBenchmarkEnabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: k8s-cis-benchmark-template + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +data: + config: |- + apiVersion: batch/v1 + kind: Job + metadata: + name: k8s-cis-benchmark + labels: + k8s-cis-benchmark: k8s-cis-benchmark + spec: + activeDeadlineSeconds: 1200 + ttlSecondsAfterFinished: 30 + template: + spec: + hostPID: true + restartPolicy: Never + tolerations: + - operator: Exists + initContainers: + - name: init-k8s-cis-benchmark + image: "{{ default .Values.global.registry .Values.busybox.image.registry }}/{{ .Values.busybox.image.repository }}:{{ .Values.busybox.image.tag }}" + imagePullPolicy: {{ .Values.busybox.image.pullPolicy }} + securityContext: + {{- toYaml .Values.busybox.securityContext | nindent 16 }} + args: + - /bin/sh + - -c + - > + set -x; + while [ 1 ]; do + nc {{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local 24235; + if [ $? -eq 0 ]; then + break; + fi + echo waiting for k8s CIS benchmark result forwarding server; sleep 5; + done; + containers: + - name: k8s-cis-benchmark + image: {{ default .Values.global.registry .Values.k8sCISBenchmark.image.registry }}/{{ .Values.k8sCISBenchmark.image.repository }}:{{ .Values.k8sCISBenchmark.image.tag }} + env: + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: K8S_NODE_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: RPC_ADDRESS + value: {{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:24235 + command: + - k8s-cis-benchmark + volumeMounts: + - name: var-lib-kubelet + mountPath: /var/lib/kubelet + readOnly: true + - name: etc-systemd + mountPath: /etc/systemd + readOnly: true + - name: etc-kubernetes + mountPath: /etc/kubernetes + readOnly: true + volumes: + - name: var-lib-kubelet + hostPath: + path: "/var/lib/kubelet" + - name: etc-systemd + hostPath: + path: "/etc/systemd" + - name: etc-kubernetes + hostPath: + path: "/etc/kubernetes" +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-discovery-clusterrole.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-discovery-clusterrole.yaml new file mode 100644 index 00000000..3ef8e2ec --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-discovery-clusterrole.yaml @@ -0,0 +1,73 @@ +# ClusterRole to allow the Panoptica agent to discover all the required +# resources on the kubernetes cluster. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "controller.fullname" . }}-k8s-discovery + labels: + {{- include "controller.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: + - "namespaces" + - "nodes" + - "pods" + - "podtemplates" + - "configmaps" + - "services" + - "serviceaccounts" + - "endpoints" + - "persistentvolumeclaims" + - "persistentvolumes" + - "replicationcontrollers" + verbs: ["get", "list"] + + - apiGroups: ["rbac.authorization.k8s.io"] + resources: + - "clusterroles" + - "clusterrolebindings" + - "roles" + - "rolebindings" + verbs: ["get", "list"] + + - apiGroups: ["admissionregistration.k8s.io"] + resources: + - "mutatingwebhookconfigurations" + - "validatingwebhookconfigurations" + verbs: ["get", "list"] + + - apiGroups: ["apiextensions.k8s.io"] + resources: + - "customresourcedefinitions" + verbs: ["get", "list"] + + - apiGroups: ["storage.k8s.io"] + resources: + - "storageclasses" + verbs: ["get", "list"] + + - apiGroups: ["apps"] + resources: + - "deployments" + - "statefulsets" + - "replicasets" + - "daemonsets" + verbs: ["get", "list"] + + - apiGroups: ["networking.k8s.io"] + resources: + - "networkpolicies" + - "ingresses" + - "ingressclasses" + verbs: ["get", "list"] + + - apiGroups: ["batch"] + resources: + - "jobs" + - "cronjobs" + verbs: ["get", "list"] + + - apiGroups: ["policy"] + resources: + - "podsecuritypolicies" + verbs: ["get", "list"] diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-discovery-clusterrolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-discovery-clusterrolebinding.yaml new file mode 100644 index 00000000..7173b513 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-discovery-clusterrolebinding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "controller.fullname" . }}-k8s-discovery + labels: + {{- include "controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "controller.fullname" . }}-k8s-discovery +subjects: + - kind: ServiceAccount + name: {{ include "controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/kafka-authz-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/kafka-authz-configmap.yaml new file mode 100644 index 00000000..eeaef914 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/kafka-authz-configmap.yaml @@ -0,0 +1,12 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "product.name" . }}-kafka-authz + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +data: + broker.port: |- + 9092 +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/kafka-injector-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/kafka-injector-configmap.yaml new file mode 100644 index 00000000..095fa50e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/kafka-injector-configmap.yaml @@ -0,0 +1,25 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "product.name" . }}-kafka-injector + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +data: + config: |- + name: {{ include "product.name" . }}-kafka-authz-injector + image: "{{ default .Values.global.registry .Values.kafkaAuthzInjector.image.registry }}/{{ .Values.kafkaAuthzInjector.image.repository }}:{{ .Values.kafkaAuthzInjector.image.tag }}" + imagePullPolicy: {{ .Values.kafkaAuthzInjector.image.pullPolicy }} + securityContext: + {{- toYaml .Values.kafkaAuthzInjector.securityContext | nindent 6 }} + volumeMounts: + - name: {{ include "product.name" . }} + mountPath: /jar + supported.broker.names: |- + {"broker":true,"cp-kafka-broker":true,"kafka-broker":true,"kafka":true} + supported.configmap.field.names: |- + {"server.properties":true,"server.config":true} + supported.start.commands: |- + {"kafka-server-start.sh":"KAFKA_NATIVE_DISTRIBUTION","docker/run":"KAFKA_DOCKER_DISTRIBUTION","kafka_run.sh":"KAFKA_NATIVE_DISTRIBUTION"} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/mutatingwebhookconfiguration.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/mutatingwebhookconfiguration.yaml new file mode 100644 index 00000000..8f79fd55 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/mutatingwebhookconfiguration.yaml @@ -0,0 +1,104 @@ +{{- if .Values.global.isContainerSecurityEnabled -}} +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: {{ include "product.name" . }}-mutating-webhook + labels: + owner: {{ include "product.name" . }} + {{- include "controller.labels" . | nindent 4 }} +webhooks: +{{- if .Values.global.isConnectionEnforcementEnabled }} + - admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + caBundle: "" + service: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + path: /webhooks/mutating/connections/pods + port: 443 + failurePolicy: Ignore + matchPolicy: Equivalent + name: secureapplication-connections-protected.pod.validator.{{ include "product.name" . }}-webhook + namespaceSelector: + matchExpressions: + - key: SecureApplication-protected + operator: In + values: + - full + - connections-only + reinvocationPolicy: Never + rules: + - apiGroups: + - '*' + apiVersions: + - '*' + operations: + - CREATE + resources: + - pods + scope: '*' + sideEffects: None + timeoutSeconds: 10 +{{- end }} + - admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + caBundle: "" + service: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + path: /webhooks/mutating/deployment/pods + port: 443 + failurePolicy: Ignore + matchPolicy: Equivalent + name: secureapplication-deployment-protected.pod.validator.{{ include "product.name" . }}-webhook + namespaceSelector: + matchExpressions: + - key: SecureApplication-protected + operator: In + values: + - full + - deployment-only + reinvocationPolicy: Never + rules: + - apiGroups: + - '*' + apiVersions: + - '*' + operations: + - CREATE + resources: + - pods + scope: '*' + sideEffects: None + timeoutSeconds: 10 + {{- if .Values.global.autoLabelEnabled }} + - admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + caBundle: "" + service: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + path: /webhooks/mutating/namespaces + port: 443 + failurePolicy: Ignore + name: namespace.mutating.{{ include "product.name" . }}-webhook + rules: + - apiGroups: + - '*' + apiVersions: + - '*' + operations: + - CREATE + resources: + - namespaces + scope: '*' + sideEffects: None + timeoutSeconds: 10 + {{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/pdb.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/pdb.yaml new file mode 100644 index 00000000..82a1de88 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/pdb.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.controller.pdb.create (not .Values.controller.persistence.enabled) -}} +apiVersion: {{ include "panoptica.capabilities.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +spec: + {{- if .Values.controller.pdb.minAvailable }} + minAvailable: {{ .Values.controller.pdb.minAvailable }} + {{- end }} + {{- if .Values.controller.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.controller.pdb.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "controller.labels" . | nindent 6 }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/post-delete-job.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/post-delete-job.yaml new file mode 100644 index 00000000..590ff73b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/post-delete-job.yaml @@ -0,0 +1,104 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "controller.fullname" . }}-post-delete + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded,hook-failed +data: + uninstall.sh: |- + #!/bin/sh -x + + kubectl -n {{ .Release.Namespace }} delete secrets --field-selector type={{ include "product.name" . }}.io/ca-root --ignore-not-found +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "controller.fullname" . }}-post-delete + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded,hook-failed +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["list", "delete"] +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "controller.fullname" . }}-post-delete + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded,hook-failed +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "controller.fullname" . }}-post-delete + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded,hook-failed +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "controller.fullname" . }}-post-delete +subjects: + - kind: ServiceAccount + name: {{ include "controller.fullname" . }}-post-delete + namespace: {{ .Release.Namespace }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "controller.fullname" . }}-post-delete + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded,hook-failed +spec: + backoffLimit: 0 + template: + metadata: + name: {{ include "controller.fullname" . }}-post-delete + spec: + restartPolicy: Never + serviceAccountName: {{ include "controller.fullname" . }}-post-delete + securityContext: + runAsNonRoot: true + runAsUser: 65532 + fsGroup: 65532 + containers: + - name: kubectl + image: "{{ default .Values.global.registry .Values.kubectl.image.registry }}/{{ .Values.kubectl.image.repository }}:{{ .Values.kubectl.image.tag }}" + imagePullPolicy: {{ .Values.kubectl.image.pullPolicy }} + command: [ "/bin/sh", "-c", "/opt/uninstall.sh" ] + volumeMounts: + - name: uninstall-script + mountPath: /opt/uninstall.sh + subPath: uninstall.sh + volumes: + - name: uninstall-script + configMap: + name: {{ include "controller.fullname" . }}-post-delete + items: + - key: uninstall.sh + path: uninstall.sh + mode: 0777 + {{- with .Values.controller.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/pvc.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/pvc.yaml new file mode 100644 index 00000000..13a8bcd3 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/pvc.yaml @@ -0,0 +1,26 @@ +{{- if .Values.controller.persistence.enabled -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + {{- if .Values.global.dummyPlaceHolderForTest }} + name: {{ include "product.name" . }}-pvc-for-test + {{- else }} + name: {{ include "product.name" . }}-{{ .Values.controller.persistence.pvcSuffix }} + {{- end }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.controller.persistence.accessMode | quote }} + resources: + requests: + storage: {{ .Values.controller.persistence.size }} + {{- if .Values.controller.persistence.storageClass }} + {{- if (eq "-" .Values.controller.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.controller.persistence.storageClass }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/role.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/role.yaml new file mode 100644 index 00000000..89b322fa --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/role.yaml @@ -0,0 +1,16 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +rules: + # Leases and configmaps are required for leader election, legacy leader + # election uses configmaps, new deploys will use leases. + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "update", "create", "delete", "list", "watch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "update", "create", "delete", "list", "watch"] \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/rolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/rolebinding.yaml new file mode 100644 index 00000000..84b49f07 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/rolebinding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "controller.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/secret.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/secret.yaml new file mode 100644 index 00000000..e214a66c --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/secret.yaml @@ -0,0 +1,12 @@ +{{- if not .Values.controller.secret.existingSecret -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +type: Opaque +data: + {{ .Values.controller.secret.sharedSecretKey | default "SHARED_SECRET" }}: {{ required "Shared secret is required!" .Values.controller.secret.sharedSecret | b64enc }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/service.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/service.yaml new file mode 100644 index 00000000..4c610614 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/service.yaml @@ -0,0 +1,82 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +spec: + type: {{ .Values.controller.service.type }} + ports: + - name: grpc-image-analysis-sbom-result-forwarding-server + port: 25235 + protocol: TCP + targetPort: 25235 + {{- if .Values.global.k8sCisBenchmarkEnabled }} + - name: grpc-k8s-cis-benchmark-result-forwarding-server + port: 24235 + protocol: TCP + targetPort: 24235 + {{- end }} + {{- if .Values.global.isContainerSecurityEnabled }} + {{- if .Values.global.isConnectionEnforcementEnabled }} + - name: {{ include "product.name" . }}-agent-sidecars + port: 24225 + protocol: TCP + targetPort: 24225 + - name: grpc-{{ include "product.name" . }}-agent-inbound-ext-auth-server + port: 24229 + protocol: TCP + targetPort: 24229 + - name: grpc-{{ include "product.name" . }}-agent-outbound-ext-auth-server + port: 24226 + protocol: TCP + targetPort: 24226 + - name: grpc-istio-adapter-server + port: 24227 + protocol: TCP + targetPort: 24227 + - name: grpc-connection-event-forwarding-server + port: 24234 + protocol: TCP + targetPort: 24234 + - name: grpc-{{ include "product.name" . }}-agent-kafka-authz-server + port: 24231 + protocol: TCP + targetPort: 24231 + - name: http-agent-kafka-opa-server + port: 8181 + protocol: TCP + targetPort: 8181 + {{- end }} + - name: {{ include "product.name" . }}-agent-webhook-server + port: 443 + protocol: TCP + targetPort: 8443 + - name: grpc-{{ include "product.name" . }}-agent-cd-server + port: 24230 + protocol: TCP + targetPort: 24230 + - name: grpc-{{ include "product.name" . }}-agent-dns-exporter-server + port: 24232 + protocol: TCP + targetPort: 24232 + {{- if .Values.global.tokenInjectionEnabled }} + - name: vault-env-log-server + port: 9514 + protocol: UDP + targetPort: 9514 + {{- end }} + {{- end }} + {{- if .Values.global.isAPISecurityEnabled }} + - name: http-wasm-filter-file-server + port: 8081 + protocol: TCP + targetPort: 8081 + - name: http-apiclarity-notification-server + port: 8082 + protocol: TCP + targetPort: 8082 + {{- end }} + selector: + {{- include "controller.selectorLabels" . | nindent 4 }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/serviceaccount.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/serviceaccount.yaml new file mode 100644 index 00000000..2d0f1a4e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.controller.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + {{- with .Values.controller.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/sidecar-injector-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/sidecar-injector-configmap.yaml new file mode 100644 index 00000000..9a5b8bcc --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/sidecar-injector-configmap.yaml @@ -0,0 +1,58 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "product.name" . }}-sidecar-injector + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + {{- if .Values.global.dummyPlaceHolderForTest }} + role: test + {{- end }} +data: + config: |- + name: dns-detector + image: "{{ default .Values.global.registry .Values.dnsDetector.image.registry }}/{{ .Values.dnsDetector.image.repository }}:{{ .Values.dnsDetector.image.tag }}" + imagePullPolicy: {{ .Values.dnsDetector.image.pullPolicy }} + args: + - -dev + - eth0 + - -pod_status_grpc_address + - {{ include "controller.fullname" . }}.{{ .Release.Namespace }}:24225 + - -capture_export_addr + - {{ include "controller.fullname" . }}.{{ .Release.Namespace }}:24232 + {{- if .Values.istio.global.alreadyInstalled }} + - -passive_capture + {{- end }} + - -assembly_debug_log + - -debug + - warning + - -quiet + securityContext: + {{- if .Values.istio.global.alreadyInstalled }} + runAsUser: 0 + {{- else }} + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsUser: 1337 + runAsGroup: 1337 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + {{- end }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + resources: + {{- toYaml .Values.dnsDetector.resources | nindent 6 }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/validatingwebhookconfiguration.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/validatingwebhookconfiguration.yaml new file mode 100644 index 00000000..f294d463 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/validatingwebhookconfiguration.yaml @@ -0,0 +1,156 @@ +{{- if .Values.global.isContainerSecurityEnabled -}} +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ include "product.name" . }}-validating-webhook + labels: + owner: {{ include "product.name" . }} + {{- include "controller.labels" . | nindent 4 }} +webhooks: + - admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + caBundle: "" + service: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + path: /webhooks/validating/pods + port: 443 + failurePolicy: Ignore + matchPolicy: Equivalent + name: secureapplication-deployment-protected.pod.validator.{{ include "product.name" . }}-webhook + namespaceSelector: + matchExpressions: + - key: SecureApplication-protected + operator: In + values: + - full + - deployment-only + objectSelector: {} + rules: + - apiGroups: + - '*' + apiVersions: + - '*' + operations: + - CREATE + resources: + - pods + scope: '*' + sideEffects: None + timeoutSeconds: 10 + {{- if .Values.global.k8sEventsEnabled }} + - admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + caBundle: "" + service: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + path: /webhooks/audit/all + port: 443 + failurePolicy: Ignore + matchPolicy: Equivalent + name: all.auditor.{{ include "product.name" . }}-webhook + namespaceSelector: {} + objectSelector: {} + rules: + - apiGroups: + - '*' + apiVersions: + - '*' + operations: + - '*' + resources: + - '*/*' + scope: '*' + sideEffects: None + timeoutSeconds: 10 + {{- end }} + - admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + caBundle: "" + service: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + path: /webhooks/jobs-owner + port: 443 + failurePolicy: Ignore + matchPolicy: Equivalent + name: jobs.owner.{{ include "product.name" . }}-webhook + namespaceSelector: {} + objectSelector: {} + rules: + - apiGroups: + - batch + apiVersions: + - v1 + operations: + - CREATE + - DELETE + resources: + - jobs + scope: '*' + sideEffects: None + timeoutSeconds: 10 + {{- if .Values.global.validateDeployerPolicy }} + - admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + caBundle: "" + service: + name: {{ include "controller.fullname" . }} + namespace: {{ .Release.Namespace }} + path: /webhooks/deployer/policy + port: 443 + failurePolicy: Ignore + matchPolicy: Equivalent + name: deployer.policy.{{ include "product.name" . }}-webhook + namespaceSelector: {} + objectSelector: {} + rules: + - apiGroups: + - apps + apiVersions: + - '*' + operations: + - CREATE + - UPDATE + resources: ["deployments", "statefulsets", "daemonsets"] + scope: '*' + - apiGroups: + - batch + apiVersions: + - '*' + operations: + - CREATE + - UPDATE + resources: ["jobs", "cronjobs"] + scope: '*' + - apiGroups: + - "" + apiVersions: + - '*' + operations: + - CREATE + - UPDATE + resources: ["pods", "configmaps"] + scope: '*' + - apiGroups: + - rbac.authorization.k8s.io + apiVersions: + - '*' + operations: + - CREATE + - UPDATE + resources: ["roles", "clusterroles"] + scope: '*' + sideEffects: None + timeoutSeconds: 10 + {{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/destinationrule.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/destinationrule.yaml new file mode 100644 index 00000000..c22516dd --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/destinationrule.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.global.isConnectionEnforcementEnabled .Values.istio.global.alreadyInstalled -}} +apiVersion: networking.istio.io/v1beta1 +kind: DestinationRule +metadata: + name: disable-mtls-to-{{ include "product.name" . }}-agent + namespace: {{ .Release.Namespace }} + labels: + owner: {{ include "product.name" . }} +spec: + host: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local" + exportTo: + - "*" + trafficPolicy: + tls: + mode: DISABLE +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.10.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.10.yaml new file mode 100644 index 00000000..f8202007 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.10.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.10 - 1.12" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.10 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.10.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.10.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.10.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.10.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.10.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.10.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.10 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.10.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.10.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.10.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.10.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.10.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.10.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.11.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.11.yaml new file mode 100644 index 00000000..f59c8227 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.11.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.11 - 1.11" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.11 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.11.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.11.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.11.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.11.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.11.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.11.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.11 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.11.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.11.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.11.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.11.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.11.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.11.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.12.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.12.yaml new file mode 100644 index 00000000..f661381d --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.12.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.12 - 1.14" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.12 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.12.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.12.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.12.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.12.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.12.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.12.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.12 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.12.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.12.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.12.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.12.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.12.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.12.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.13.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.13.yaml new file mode 100644 index 00000000..057c85bd --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.13.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.13 - 1.16" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.13 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.13.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.13.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.13.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.13.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.13.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.13.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.13 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.13.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.13.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.13.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.13.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.13.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.13.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.14.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.14.yaml new file mode 100644 index 00000000..9e96015b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.14.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.14 - 1.16" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.14 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.14.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.14.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.14.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.14.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.14.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.14.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.14 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.14.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.14.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.14.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.14.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.14.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.14.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.15.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.15.yaml new file mode 100644 index 00000000..147cd7b7 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.15.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.15 - 1.17" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.15 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.15.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.15.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.15.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.15.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.15.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.15.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.15 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.15.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.15.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.15.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.15.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.15.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.15.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.16.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.16.yaml new file mode 100644 index 00000000..e6ff5f8c --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.16.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.16 - 1.18" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.16 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.16.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.16.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.16.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.16.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.16.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.16.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.16 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.16.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.16.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.16.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.16.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.16.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.16.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.17.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.17.yaml new file mode 100644 index 00000000..f8951b8b --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.17.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.17 - 1.19" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.17 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.17.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.17.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.17.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.17.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.17.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.17.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.17 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.17.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.17.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.17.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.17.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.17.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.17.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.18.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.18.yaml new file mode 100644 index 00000000..2c0495d6 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.18.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.18 - 1.20" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.18 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.18.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.18.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.18.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.18.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.18.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.18.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.18 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.18.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.18.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.18.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.18.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.18.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.18.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.19.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.19.yaml new file mode 100644 index 00000000..473357ad --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.19.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.19 - 1.21" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.19 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.19.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.19.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.19.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.19.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.19.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.19.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.19 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.19.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.19.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.19.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.19.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.19.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.19.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.9.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.9.yaml new file mode 100644 index 00000000..d46b8d09 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.9.yaml @@ -0,0 +1,385 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.9 - 1.11" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-1.9 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: pod +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: pod + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.9.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24226 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24226_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: CLUSTER + match: + context: ANY + cluster: + name: "inbound-ext-authz" + proxy: + proxyVersion: ^1\.9.* + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STRICT_DNS + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "{{ include "controller.fullname" . }}.{{ .Release.Namespace }}" + port_value: 24229 + {{- if and .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) }} + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + sni: outbound_.24229_._.{{ include "controller.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + common_tls_context: + alpn_protocols: + - "istio-peer-exchange" + - "istio" + - "h2" + tls_certificate_sds_secret_configs: + - name: default + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + combined_validation_context: + default_validation_context: + match_subject_alt_names: + - exact: spiffe://cluster.local/ns/{{ .Release.Namespace }}/sa/{{ include "controller.serviceAccountName" . }} + validation_context_sds_secret_config: + name: "ROOTCA" + sds_config: + api_config_source: + api_type: "GRPC" + grpc_services: + - envoy_grpc: + cluster_name: "sds-grpc" + set_node_on_first_message_only: true + transport_api_version: V3 + initial_fetch_timeout: 0s + resource_api_version: V3 + {{- end }} + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.9.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.9.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.9.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.9.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- if .Values.istio.expansion.enabled -}} +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: ext-authz-expansion-1.9 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} + workload-type: expansion +spec: + workloadSelector: + labels: + {{ include "product.name" . }}.io/envoy-auth-config: expansion + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.9.* + context: ANY + cluster: + name: "outbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "outbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "outbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24226 + - applyTo: CLUSTER + match: + proxy: + proxyVersion: ^1\.9.* + context: ANY + cluster: + name: "inbound-ext-authz" + patch: + operation: ADD + value: # cluster specification + name: "inbound-ext-authz" + type: STATIC + http2_protocol_options: {} + connect_timeout: 10s + load_assignment: + cluster_name: "inbound-ext-authz" + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "127.0.0.1" + port_value: 24229 + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.9.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.9.* + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: outbound-ext-authz + - applyTo: NETWORK_FILTER + match: + proxy: + proxyVersion: ^1\.9.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.network.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz" + stat_prefix: ext_authz + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz + - applyTo: HTTP_FILTER + match: + proxy: + proxyVersion: ^1\.9.* + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: "envoy.filters.http.ext_authz" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz" + transport_api_version: V3 + include_peer_certificate: true + failure_mode_allow: {{ .Values.global.connectionFailPolicyAllow }} + grpc_service: + envoy_grpc: + cluster_name: inbound-ext-authz +{{- end }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.10.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.10.yaml new file mode 100644 index 00000000..9e59cb8e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.10.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.10 - 1.12" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.10 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.10.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.11.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.11.yaml new file mode 100644 index 00000000..37e80725 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.11.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.11 - 1.11" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.11 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.11.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.12.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.12.yaml new file mode 100644 index 00000000..f78fc031 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.12.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.12 - 1.14" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.12 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.12.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.13.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.13.yaml new file mode 100644 index 00000000..f304926d --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.13.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.13 - 1.16" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.13 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.13.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.14.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.14.yaml new file mode 100644 index 00000000..ca7c742a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.14.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.14 - 1.16" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.14 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.14.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.15.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.15.yaml new file mode 100644 index 00000000..ce1e15bb --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.15.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.15 - 1.17" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.15 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.15.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.16.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.16.yaml new file mode 100644 index 00000000..79ffc416 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.16.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.16 - 1.18" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.16 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.16.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.17.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.17.yaml new file mode 100644 index 00000000..df1ac658 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.17.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.17 - 1.19" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.17 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.17.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.18.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.18.yaml new file mode 100644 index 00000000..152562c8 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.18.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.18 - 1.20" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.18 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.18.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.19.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.19.yaml new file mode 100644 index 00000000..7adbb1a6 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.19.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.19 - 1.21" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.19 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.19.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.9.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.9.yaml new file mode 100644 index 00000000..9df858a5 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.9.yaml @@ -0,0 +1,36 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.9 - 1.11" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: passthrough-cluster-tls-1.9 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: CLUSTER + match: + proxy: + proxyVersion: '^1\.9.*' + context: ANY + cluster: + name: "PassthroughClusterTLS" + patch: + operation: ADD + value: # cluster specification + name: PassthroughClusterTLS + connect_timeout: 10s + type: ORIGINAL_DST + lb_policy: CLUSTER_PROVIDED + protocol_selection: "USE_DOWNSTREAM_PROTOCOL" + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + validation_context: + trusted_ca: + filename: /etc/ssl/certs/ca-certificates.crt +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/peerauth.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/peerauth.yaml new file mode 100644 index 00000000..dd235834 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/peerauth.yaml @@ -0,0 +1,10 @@ +{{- if and .Values.global.isConnectionEnforcementEnabled .Values.global.isAPISecurityEnabled (not .Values.istio.global.alreadyInstalled) -}} +apiVersion: "security.istio.io/v1beta1" +kind: "PeerAuthentication" +metadata: + name: {{ include "product.name" . }}-mtls-pa + namespace: {{ .Release.Namespace }} +spec: + mtls: + mode: STRICT +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/post-delete-job.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/post-delete-job.yaml new file mode 100644 index 00000000..8fc79719 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/post-delete-job.yaml @@ -0,0 +1,153 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "controller.fullname" . }}-istio-post-delete + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded,hook-failed +data: + uninstall.sh: |- + #!/bin/sh -x + + kubectl delete destinationrules.networking.istio.io --all-namespaces -l owner={{ include "product.name" . }} --ignore-not-found + kubectl delete peerauthentications.security.istio.io --all-namespaces -l owner={{ include "product.name" . }} --ignore-not-found + kubectl delete serviceentries.networking.istio.io --all-namespaces -l owner={{ include "product.name" . }} --ignore-not-found + kubectl delete virtualservices.networking.istio.io --all-namespaces -l owner={{ include "product.name" . }} --ignore-not-found + kubectl delete envoyfilter.networking.istio.io --all-namespaces -l owner={{ include "product.name" . }} --ignore-not-found + kubectl delete secrets --all-namespaces --field-selector type=istio.io/custom-id --ignore-not-found + kubectl delete secrets --all-namespaces --field-selector type=istio.io/key-and-cert --ignore-not-found + + function refresh_all_pods() { + kubectl -n $1 rollout restart deployments + kubectl -n $1 rollout restart daemonsets + kubectl -n $1 rollout restart statefulsets + } + + function refresh_all_connections_only_protected_namespaces() { + PROTECTED_NAMESPACE_LIST=$(kubectl get ns -l SecureApplication-protected=connections-only -o jsonpath='{.items[*].metadata.name}') + echo "Refreshing pods in all connections-only protected namespaces" + for namespace_name in $PROTECTED_NAMESPACE_LIST ; do + refresh_all_pods $namespace_name + done + } + + function refresh_all_full_protected_namespaces() { + PROTECTED_NAMESPACE_LIST=$(kubectl get ns -l SecureApplication-protected=full -o jsonpath='{.items[*].metadata.name}') + echo "Refreshing pods in all full protected namespaces" + for namespace_name in $PROTECTED_NAMESPACE_LIST ; do + refresh_all_pods $namespace_name + done + } + + function refresh_all_protected_namespaces() { + refresh_all_connections_only_protected_namespaces + refresh_all_full_protected_namespaces + } + + refresh_all_protected_namespaces +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "controller.fullname" . }}-istio-post-delete + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded,hook-failed +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["list", "delete"] + - apiGroups: ["networking.istio.io"] + resources: ["destinationrules", "serviceentries", "virtualservices", "envoyfilters"] + verbs: ["list", "delete"] + - apiGroups: ["security.istio.io"] + resources: ["peerauthentications"] + verbs: ["list", "delete"] + - apiGroups: ["apps"] + resources: ["statefulsets", "daemonsets", "deployments"] + verbs: ["list", "patch"] + - apiGroups: [""] + resources: ["namespaces"] + verbs: ["list"] +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "controller.fullname" . }}-istio-post-delete + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded,hook-failed +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "controller.fullname" . }}-istio-post-delete + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded,hook-failed +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "controller.fullname" . }}-istio-post-delete +subjects: + - kind: ServiceAccount + name: {{ include "controller.fullname" . }}-istio-post-delete + namespace: {{ .Release.Namespace }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "controller.fullname" . }}-istio-post-delete + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-delete + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded,hook-failed +spec: + backoffLimit: 0 + template: + metadata: + name: {{ include "controller.fullname" . }}-istio-post-delete + spec: + restartPolicy: Never + serviceAccountName: {{ include "controller.fullname" . }}-istio-post-delete + securityContext: + runAsNonRoot: true + runAsUser: 65532 + fsGroup: 65532 + containers: + - name: kubectl + image: "{{ default .Values.global.registry .Values.kubectl.image.registry }}/{{ .Values.kubectl.image.repository }}:{{ .Values.kubectl.image.tag }}" + imagePullPolicy: {{ .Values.kubectl.image.pullPolicy }} + command: [ "/bin/sh", "-c", "/opt/uninstall.sh" ] + volumeMounts: + - name: uninstall-script + mountPath: /opt/uninstall.sh + subPath: uninstall.sh + volumes: + - name: uninstall-script + configMap: + name: {{ include "controller.fullname" . }}-istio-post-delete + items: + - key: uninstall.sh + path: uninstall.sh + mode: 0777 + {{- with .Values.controller.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/sidecar.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/sidecar.yaml new file mode 100644 index 00000000..4817db94 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/sidecar.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.global.isConnectionEnforcementEnabled .Values.istio.global.serviceDiscoveryIsolationEnabled -}} +apiVersion: networking.istio.io/v1beta1 +kind: Sidecar +metadata: + name: default + namespace: istio-system +spec: + egress: + - hosts: + - "./*" + - "istio-system/*" + - "{{ .Release.Namespace }}/*" +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.10.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.10.yaml new file mode 100644 index 00000000..8fabf8b1 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.10.yaml @@ -0,0 +1,81 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.10 - 1.12" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.10 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.10.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.10 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.10.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.11.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.11.yaml new file mode 100644 index 00000000..180d5c29 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.11.yaml @@ -0,0 +1,81 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.11 - 1.13" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.11 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.11.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.11 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.11.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.12.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.12.yaml new file mode 100644 index 00000000..1065bd7f --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.12.yaml @@ -0,0 +1,81 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.12 - 1.14" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.12 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.12.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.12 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.12.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.13.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.13.yaml new file mode 100644 index 00000000..684dccc9 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.13.yaml @@ -0,0 +1,83 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.13 - 1.16" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.13 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.13.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.13 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.13.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.14.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.14.yaml new file mode 100644 index 00000000..c6541d84 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.14.yaml @@ -0,0 +1,83 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.14 - 1.16" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.14 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.14.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.14 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.14.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.15.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.15.yaml new file mode 100644 index 00000000..e6223e89 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.15.yaml @@ -0,0 +1,83 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.15 - 1.17" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.15 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.15.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.15 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.15.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.16.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.16.yaml new file mode 100644 index 00000000..7cbcf84a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.16.yaml @@ -0,0 +1,83 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.16 - 1.18" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.16 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.16.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.16 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.16.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.17.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.17.yaml new file mode 100644 index 00000000..93897630 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.17.yaml @@ -0,0 +1,83 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.17 - 1.19" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.17 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.17.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.17 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.17.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.18.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.18.yaml new file mode 100644 index 00000000..7f133cc4 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.18.yaml @@ -0,0 +1,83 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.18 - 1.20" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.18 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.18.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.18 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.18.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.19.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.19.yaml new file mode 100644 index 00000000..85293350 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.19.yaml @@ -0,0 +1,83 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.19 - 1.21" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.19 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.19.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.19 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + priority: -1 + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.19.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.9.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.9.yaml new file mode 100644 index 00000000..e7fedbbe --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.9.yaml @@ -0,0 +1,81 @@ +{{- if .Values.global.isConnectionEnforcementEnabled -}} +{{- if semverCompare "1.9 - 1.11" .Values.istio.global.version -}} +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: stackdriver-filter-1.9 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: HTTP_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.9.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.http_connection_manager" + subFilter: + name: "envoy.filters.http.router" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: tcp-stackdriver-filter-1.9 + namespace: istio-system + labels: + owner: {{ include "product.name" . }} +spec: + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + proxy: + proxyVersion: '^1\.9.*' + listener: + filterChain: + filter: + name: "envoy.filters.network.tcp_proxy" + patch: + operation: INSERT_BEFORE + value: + name: istio.stackdriver + typed_config: + "@type": type.googleapis.com/udpa.type.v1.TypedStruct + type_url: type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm + value: + config: + root_id: stackdriver_inbound + configuration: + "@type": "type.googleapis.com/google.protobuf.StringValue" + value: | + {"disable_host_header_fallback":false,"disable_server_access_logging":false,"enable_mesh_edges_reporting":false} + vm_config: + vm_id: stackdriver_inbound + runtime: envoy.wasm.runtime.null + code: + local: { inline_string: envoy.wasm.null.stackdriver } +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/seccomp-installer/_helpers.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/seccomp-installer/_helpers.tpl new file mode 100644 index 00000000..588e9151 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/seccomp-installer/_helpers.tpl @@ -0,0 +1,45 @@ +{{- define "seccomp-installer.name" -}} +{{- "seccomp-installer" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "seccomp-installer.fullname" -}} +{{- "seccomp-installer" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "seccomp-installer.labels" -}} +helm.sh/chart: {{ include "panoptica.chart" . }} +{{ include "seccomp-installer.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.global.extraLabels }} +{{ toYaml $.Values.global.extraLabels }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "seccomp-installer.selectorLabels" -}} +app: {{ include "seccomp-installer.name" . }} +app.kubernetes.io/name: {{ include "seccomp-installer.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "seccomp-installer.serviceAccountName" -}} +{{- if .Values.seccompInstaller.serviceAccount.create }} +{{- default (include "seccomp-installer.fullname" .) .Values.seccompInstaller.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.seccompInstaller.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/seccomp-installer/serviceaccount.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/seccomp-installer/serviceaccount.yaml new file mode 100644 index 00000000..35d940f1 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/seccomp-installer/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.global.isContainerSecurityEnabled .Values.seccompInstaller.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: seccomp-installer + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} + {{- with .Values.seccompInstaller.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/clusterrolebinding.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/clusterrolebinding.yaml new file mode 100644 index 00000000..71c309cf --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if not .Values.global.isManagedByHelm -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "product.name" . }}-upgrader + labels: + {{- include "controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: ServiceAccount + name: {{ include "product.name" . }}-upgrader + namespace: {{ .Release.Namespace }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/serviceaccount.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/serviceaccount.yaml new file mode 100644 index 00000000..92b223b5 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/serviceaccount.yaml @@ -0,0 +1,9 @@ +{{- if not .Values.global.isManagedByHelm -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "product.name" . }}-upgrader + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/upgrader-template-configmap.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/upgrader-template-configmap.yaml new file mode 100644 index 00000000..676e9eef --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/upgrader-template-configmap.yaml @@ -0,0 +1,72 @@ +{{- if not .Values.global.isManagedByHelm }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: upgrader-job-template + namespace: {{ .Release.Namespace }} + labels: + {{- include "controller.labels" . | nindent 4 }} +data: + config: |- + apiVersion: batch/v1 + kind: Job + metadata: + name: upgrader + namespace: {{ .Release.Namespace }} + labels: + app: upgrader + spec: + activeDeadlineSeconds: 1200 + ttlSecondsAfterFinished: 30 + backoffLimit: 0 + template: + spec: + restartPolicy: Never + serviceAccountName: {{ include "product.name" . }}-upgrader + containers: + - name: upgrader + imagePullPolicy: {{ .Values.upgrader.image.pullPolicy }} + args: + - run + - --log-level + - {{ .Values.controller.logLevel }} + env: + - name: AGENT_ID + value: {{ required "Agent ID is required!" .Values.controller.agentID | quote }} + - name: MANAGEMENT_HOST + value: {{ .Values.global.mgmtHostname | quote }} + - name: SHARED_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.controller.secret.existingSecret | default (include "controller.fullname" .) }} + key: {{ .Values.controller.secret.sharedSecretKey | default "SHARED_SECRET" }} + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: XDG_CACHE_HOME + value: /tmp + - name: SCRIPT_API_VERSION + value: 1 + securityContext: + {{- toYaml .Values.upgrader.securityContext | nindent 16 }} + resources: + {{- toYaml .Values.upgrader.resources | nindent 16 }} + volumeMounts: + - mountPath: /tmp + name: tmp-volume + volumes: + - name: tmp-volume + emptyDir: {} + securityContext: + {{- toYaml .Values.upgrader.podSecurityContext | nindent 12 }} + {{- with .Values.upgrader.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.upgrader.tolerations }} + tolerations: + {{- toYaml . | nindent 12 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/values.yaml new file mode 100644 index 00000000..6b09bb30 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/values.yaml @@ -0,0 +1,516 @@ +global: + # -- Override product name. Defaults to chart name. + productNameOverride: "portshift" + # -- Override detected cluster version. + kubeVersionOverride: "" + # @ignored + isManagedByHelm: true + # @ignored - used for helm lint testing to skip istio/vault chart verification + skipCrossChartsVerification: false + # -- Panoptica SaaS URL. Used to override default URL for local testing. + mgmtHostname: "" + # -- Indicates whether kubernetes security is enabled. + isContainerSecurityEnabled: true + # -- Indicates whether K8s CIS benchmark is enabled. + k8sCisBenchmarkEnabled: true + # -- Indicates whether SSH monitoring is enabled. + isSSHMonitorEnabled: true + # -- Indicates whether Deployer Policy enforcement is enabled. + validateDeployerPolicy: false + # -- Indicates whether K8s Events monitoring is enabled. + k8sEventsEnabled: true + # -- Indicates whether API security is enabled. + isAPISecurityEnabled: false + # -- Indicates whether connection enforcement is enabled. If true, make sure istio is installed by using panoptica istio chart or an upstream istio is already installed. + isConnectionEnforcementEnabled: false + # -- Indicates whether token injection feature is enabled. If true, make sure vault is installed by using panoptica vault chart. + tokenInjectionEnabled: false + # -- Indicates whether istio should provision workload certificates using a custom certificate authority that integrates with the Kubernetes CSR API. + isExternalCaEnabled: false + # -- Indicates whether installed in an OpenShift environment. + isOpenShift: false + # -- Proxy address to use for HTTP request if needed. + httpProxy: "" + # -- Proxy address to use for HTTPs request if needed. In most cases, this is the same as `httpProxy`. + httpsProxy: "" + # -- Registry for the Panoptica images. If replaced with a local registry need to make sure all images are pulled into the local registry. + registry: "gcr.io/eticloud/k8sec" + # -- Configures telemetry frequency (in seconds) for reporting duration. + sendTelemetriesIntervalSec: 30 + # -- If false, connections on protected namespaces will be blocked if the controller is not responding. + connectionFailPolicyAllow: true + # -- If false, pods creation on protected namespaces will be blocked if the controller is not responding. + environmentFailurePolicyAllow: true + # -- Indicates whether TLS inspection is enabled. If true, the controller will be able to decrypt and re-encrypt HTTPS traffic for connections to be inspected via layer 7 attributes. + enableTlsInspection: false + # -- Placeholder used for tests. + dummyPlaceHolderForTest: false + # -- Indicates whether auto label is enabled. If true, new namespaces will be labeled with the protection label. + autoLabelEnabled: false + # -- Indicates whether to identity pods whose templates originated from the Panoptica CD plugin. See `CD Pod template` section in https://panoptica.readme.io/docs/deploy-on-a-kubernetes-cluster for more info. + cdValidation: false + # -- Indicates whether to identity pods only if all images are signed by a trusted signer. See https://panoptica.readme.io/docs/trusted-signers for more info. + ciImageSignatureValidation: false + # -- Indicates whether to identity pods only if all image hashes are known to Panoptica. See `CI image hash validation` section in https://panoptica.readme.io/docs/deploy-on-a-kubernetes-cluster for more info. + ciImageValidation: false + # -- Indicates whether to identity pods only if all images are pulled from trusted registries. See `Restrict Registries` section in https://panoptica.readme.io/docs/deploy-on-a-kubernetes-cluster for more info. + restrictRegistries: false + # -- Indicates whether the controller should preserve the original source ip of inbound connections. + preserveOriginalSourceIp: false + # -- Allow labelling resources with custom key/value pairs. + extraLabels: {} +# key: value + +controller: + nameOverride: "portshift-agent" + fullnameOverride: "portshift-agent" + + # -- Configure controller replica count number in case autoscaling is disabled. + replicaCount: 1 + + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: k8s_agent + tag: fdb16f4d5c28fef6538d01b07ed2520bc9253809 + pullPolicy: IfNotPresent + + imagePullSecrets: [] + + # -- Logging level (debug, info, warning, error, fatal, panic). + logLevel: warning + + secret: + # -- [Required if controller.existingSecret isn't set] Shared secret used by the controller to communicate with the SaaS, should be extracted from SaaS after cluster creation. + sharedSecret: "" + # -- Existing secret that contains shared secret used by the controller to communicate with the SaaS. + existingSecret: "" + # -- Shared secret key is the key of the shared secret, default: SHARED_SECRET. + sharedSecretKey: "" + + # -- [Required] Controller identification, should be extracted from SaaS after cluster creation. + agentID: "" + + serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + + podSecurityContext: + fsGroup: 1001 + + securityContext: + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsGroup: 1001 + runAsUser: 1001 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + + service: + type: ClusterIP + + resources: + requests: + cpu: 500m + memory: 2048Mi + + autoscaling: + enabled: true + minReplicas: 1 + maxReplicas: 5 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + + pdb: + create: true + minAvailable: 1 + # maxUnavailable: 1 + + # -- Node labels for controller pod assignment + nodeSelector: + kubernetes.io/os: linux + + tolerations: [] + + affinity: {} + + persistence: + # -- Enable persistence using Persistent Volume Claims + enabled: false + pvcSuffix: pvc-fdb16f4d5c28fef6538d01b07ed2520bc9253809 + accessMode: "ReadWriteOnce" + # -- The storage space that should be claimed from the persistent volume + size: 100Mi + # -- If defined, storageClassName will be set to the defined storageClass. + # If set to "-", storageClassName will be set to an empty string (""), which disables dynamic provisioning. + # If undefined or set to null (the default), no storageClassName spec is set, + # choosing 'standard' storage class available with the default provisioner (gcd-pd on GKE, hostpath on minikube, etc). + storageClass: + +apiclarity: + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: apiclarity + tag: 9a09d167c27046e6d76a96e6e4f248f166b9fc8f + pullPolicy: IfNotPresent + + imagePullSecrets: [] + + # -- Logging level (debug, info, warning, error, fatal, panic). + logLevel: warning + + traceWasmFilterSHA256: 5f48a298d47422f6fb8e03b5c856fae5c4aaab60b8b9e9f28a13ca34d22bf0b7 + + traceSource: + # -- Indicates whether istio supply traces. + istio: false + # -- Indicates whether external GWs supply traces. + external: false + + serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + + podSecurityContext: + fsGroup: 1000 + + securityContext: + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsGroup: 1000 + runAsUser: 1000 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + + resources: + limits: + cpu: 1000m + memory: 1000Mi + requests: + cpu: 100m + memory: 200Mi + + # -- Node labels for pod assignment + nodeSelector: + kubernetes.io/os: linux + + tolerations: [] + + affinity: {} + + persistence: + accessMode: "ReadWriteOnce" + # -- The storage space that should be claimed from the persistent volume + size: 100Mi + # -- If defined, storageClassName will be set to the defined storageClass. + # If set to "-", storageClassName will be set to an empty string (""), which disables dynamic provisioning. + # If undefined or set to null (the default), no storageClassName spec is set, + # choosing 'standard' storage class available with the default provisioner (gcd-pd on GKE, hostpath on minikube, etc). + storageClass: + + fuzzer: + # Indicates whether API security fuzz test is enabled. + enabled: false + + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: scn-dast + tag: b0e698ea50aa701d22a1f8fbe549d45c340e0b91 + pullPolicy: Always + + # -- Configure fuzzer labels + labels: + app: fuzzer + + debug: false + + securityContext: + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsGroup: 1001 + runAsUser: 1001 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + + resources: + requests: + memory: "200Mi" + cpu: "100m" + limits: + memory: "1000Mi" + cpu: "200m" + + # -- Node labels for pod assignment + nodeSelector: + kubernetes.io/os: linux + + affinity: {} + +apiclarity-postgresql: + image: + # -- Image registry, must be set to override the dependency registry. + registry: gcr.io/eticloud/k8sec + repository: bitnami/postgresql + tag: 14.4.0-debian-11-r4 + pullPolicy: IfNotPresent + + ## initdb parameters + # initdb: + ## ConfigMap with scripts to be run at first boot + ## NOTE: This will override initdb.scripts + # scriptsConfigMap + ## Secret with scripts to be run at first boot (in case it contains sensitive information) + ## NOTE: This can work along initdbScripts or initdbScriptsConfigMap + # scriptsSecret: + ## Specify the PostgreSQL username and password to execute the initdb scripts + # user: + # password: + + ## Setup database name and password + auth: + existingSecret: apiclarity-postgresql-secret + database: apiclarity + + ## Enable security context + containerSecurityContext: + enabled: true + runAsUser: 1001 + runAsNonRoot: true + + ## By default, postgresql full name includes the release name, we don't want it. + fullnameOverride: "apiclarity-postgresql" + +istio: + global: + # -- Indicates whether istio is already installed and not by Panoptica charts. + alreadyInstalled: false + # -- Indicates what version of istio is running, change only if `alreadyInstalled` is set to true. + version: "1.19.0" + # Indicates whether istio service information will be synced only to proxies in the same namespace. + serviceDiscoveryIsolationEnabled: false + + expansion: + enabled: false + +kafkaAuthzInjector: + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: kafka-authz + tag: e647ba66cf10897ee6e07a3d6d81b2148d0a47be + pullPolicy: Always + + securityContext: + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsGroup: 1001 + runAsUser: 1001 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + +dnsDetector: + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: gopassivedns + tag: 0c7330b51a07cdebe13e57b1d1a33134cbbe04ce + pullPolicy: IfNotPresent + + resources: + requests: + memory: 50Mi + cpu: 20m + limits: + memory: 100Mi + cpu: 200m + +seccompInstaller: + serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +k8sCISBenchmark: + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: k8s-cis-benchmark + tag: f5b0490258b1cb87ce6eddc2a3083482135dcf5c + + # -- Node labels for pod assignment + nodeSelector: + kubernetes.io/os: linux + +imageAnalysis: + # -- Scanner jobs namespace. + # If left blank, the scanner jobs will run in release namespace. + # If set, the scanner jobs will run in the given namespace unless the image requires image pull secrets which are located in a target pod + jobDefaultNamespace: "" + + registry: + skipVerifyTlS: "false" + useHTTP: "false" + + # -- Node labels for controller pod assignment + nodeSelector: + kubernetes.io/os: linux + + tolerations: [] + + sbom: + enabled: true + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: image-analyzer + tag: 5f969c4535b52368ff7e288f6c9a2ce8bea019b0 + + podSecurityContext: + fsGroup: 1001 + + securityContext: + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsGroup: 1001 + runAsUser: 1001 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + + resources: + requests: + memory: "50Mi" + cpu: "50m" + limits: + memory: "2000Mi" + cpu: "1000m" + + cisDockerBenchmark: + enabled: false + + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: cis-docker-benchmark + tag: a281d02d480ba3fc815d176731fa9412fe872ad3 + + podSecurityContext: + fsGroup: 1001 + + securityContext: + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsGroup: 1001 + runAsUser: 1001 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + + resources: + requests: + memory: "50Mi" + cpu: "50m" + limits: + memory: "1000Mi" + cpu: "1000m" + + # -- The max number of scanner jobs that will run in the cluster in parallel for image analysis in total + parallelScanners: 4 + +kubectl: + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: kubectl + tag: v1.27.1 + pullPolicy: IfNotPresent + +busybox: + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: curlimages/curl + tag: latest + pullPolicy: IfNotPresent + + securityContext: + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsGroup: 1001 + runAsUser: 1001 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + +upgrader: + image: + pullPolicy: Always + + podSecurityContext: + fsGroup: 1001 + + securityContext: + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsGroup: 1001 + runAsUser: 1001 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + + resources: + requests: + memory: 50Mi + cpu: 50m + limits: + memory: 1000Mi + cpu: 1000m + + # -- Node labels for pod assignment + nodeSelector: + kubernetes.io/os: linux + + tolerations: [] + +vaultEnv: + image: + # -- Image registry, used to override global.registry if needed. + registry: "" + repository: bank-vaults/vault-env + tag: v1.21.0 diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/templates/NOTES.txt b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/templates/NOTES.txt new file mode 100644 index 00000000..68e8ce8a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/templates/NOTES.txt @@ -0,0 +1,5 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/templates/_helpers.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/templates/_helpers.tpl new file mode 100644 index 00000000..ebc5fe52 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "appdynamics-security-collector.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "appdynamics-security-collector.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "appdynamics-security-collector.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "appdynamics-security-collector.labels" -}} +helm.sh/chart: {{ include "appdynamics-security-collector.chart" . }} +{{ include "appdynamics-security-collector.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "appdynamics-security-collector.selectorLabels" -}} +app.kubernetes.io/name: {{ include "appdynamics-security-collector.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "appdynamics-security-collector.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "appdynamics-security-collector.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/values.yaml new file mode 100644 index 00000000..14bf7e61 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/values.yaml @@ -0,0 +1,7 @@ +panoptica: + k8sEventsEnabled: false + isContainerSecurityEnabled: false + controller: + agentID: "" + secret: + sharedSecret: "" diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/ci/appdynamics-collectors-values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/ci/appdynamics-collectors-values.yaml new file mode 100644 index 00000000..3ae55f6a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/ci/appdynamics-collectors-values.yaml @@ -0,0 +1,8 @@ +global: + clusterName: test + +appdynamics-otel-collector: + client_id: client-id-test + client_secret: client-secret-test + token_url: token-url-test + endpoint: endpoint-test \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/certs.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/certs.yaml new file mode 100644 index 00000000..cbce506a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/certs.yaml @@ -0,0 +1,59 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: selfsigned-issuer +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: my-selfsigned-ca + namespace: appdynamics +spec: + isCA: true + commonName: my-selfsigned-ca + secretName: root-secret + privateKey: + algorithm: ECDSA + size: 256 + issuerRef: + name: selfsigned-issuer + kind: ClusterIssuer + group: cert-manager.io +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: ca-cert + namespace: appdynamics +spec: + ca: + secretName: root-secret +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: server-cert + namespace: appdynamics +spec: + secretName: server-secret + issuerRef: + name: ca-cert + kind: Issuer + commonName: clustermon-service + dnsNames: + - appdynamics-otel-collector-service + - appdynamics-otel-collector-service.appdynamics.svc.cluster.local +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: client-cert + namespace: appdynamics +spec: + secretName: client-secret + issuerRef: + name: ca-cert + kind: Issuer + commonName: client \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/complex-and-or.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/complex-and-or.yaml new file mode 100644 index 00000000..3f9d6f84 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/complex-and-or.yaml @@ -0,0 +1,43 @@ +global: + clusterName: "ClusterName" +appdynamics-cloud-k8s-monitoring: + install: + clustermon: true + defaultInfraCollectors: true + logCollector: true + logCollectorConfig: + container: + - condition: + or: + - equals: + kubernetes.container.name: log-gen-app-log4j-win + - equals: + kubernetes.container.name: log-gen-app-log4j-win-test + config: + multiLinePattern: '^\d{4}-\d{2}-\d{2}' + multiLineNegate: true + multiLineMatch: after + messageParser: + log4J: + enabled: true + pattern: "%d{yyyy-MM-dd'T'HH:mm:ss} %p %C{1.} [%t] %m%n" + - condition: + and: + - equals: + kubernetes.container.name: log-gen-app-log4j-win + - equals: + kubernetes.container.name: log-gen-app-log4j + config: + multiLinePattern: '^\d{4}-\d{2}-\d{2}' + multiLineNegate: true + multiLineMatch: after + messageParser: + log4J: + enabled: true + pattern: "%d{yyyy-MM-dd'T'HH:mm:ss} %p %C{1.} [%t] %m%n" + +appdynamics-otel-collector: + clientId: + clientSecret: + endpoint: + tokenUrl: \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/complex.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/complex.yaml new file mode 100644 index 00000000..5f4cb9f1 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/complex.yaml @@ -0,0 +1,333 @@ +global: + clusterName: "ClusterName" +appdynamics-cloud-k8s-monitoring: + install: + clustermon: true + defaultInfraCollectors: true + logCollector: true + logCollectorConfig: + filebeatYaml: |- + filebeat.autodiscover: + providers: + - type: kubernetes + node: ${NODE_NAME} + labels.dedot: false + annotations.dedot: false + hints.enabled: true + hints.default_config.enabled: false + templates: + - condition: + equals: + kubernetes.container.name: log-gen-app-log4j + config: + - type: filestream + id: fsid-${data.kubernetes.pod.name}-${data.kubernetes.container.id} + close_removed: false + clean_removed: false + paths: + - /var/log/containers/${data.kubernetes.pod.name}*${data.kubernetes.container.id}.log + parsers: + - container: + stream: all + format: auto + - multiline: + type: pattern + pattern: '^\d{4}-\d{2}-\d{2}' + negate: true + match: after + prospector.scanner.symlinks: true + processors: + - copy_fields: + fields: + - from: kubernetes.pod.name + to: fields.k8s.pod.name + fail_on_error: false + ignore_missing: true + - copy_fields: + fields: + - from: kubernetes.deployment.name + to: fields.k8s.workload.name + fail_on_error: false + ignore_missing: true + - add_fields: + target: _message_parser + fields: + type: log4j + pattern: "%d{yyyy-MM-dd'T'HH:mm:ss} %p %C{1.} [%t] %m%n" + - condition: + equals: + kubernetes.container.name: log-gen-app-log4j2 + config: + - type: filestream + id: fsid-${data.kubernetes.pod.name}-${data.kubernetes.container.id} + close_removed: false + clean_removed: false + paths: + - /var/log/containers/${data.kubernetes.pod.name}*${data.kubernetes.container.id}.log + parsers: + - container: + stream: all + format: auto + - multiline: + type: pattern + pattern: '^\d{4}-\d{2}-\d{2}' + negate: true + match: after + prospector.scanner.symlinks: true + processors: + - copy_fields: + fields: + - from: kubernetes.pod.name + to: fields.k8s.pod.name + fail_on_error: false + ignore_missing: true + - copy_fields: + fields: + - from: kubernetes.deployment.name + to: fields.k8s.workload.name + fail_on_error: false + ignore_missing: true + - add_fields: + target: _message_parser + fields: + type: log4j + pattern: "%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" + - condition: + equals: + kubernetes.container.name: log-gen-app-logback + config: + - type: filestream + id: fsid-${data.kubernetes.pod.name}-${data.kubernetes.container.id} + close_removed: false + clean_removed: false + paths: + - /var/log/containers/${data.kubernetes.pod.name}*${data.kubernetes.container.id}.log + parsers: + - container: + stream: all + format: auto + - multiline: + type: pattern + pattern: '^\d{4}-\d{2}-\d{2}' + negate: true + match: after + prospector.scanner.symlinks: true + processors: + - copy_fields: + fields: + - from: kubernetes.pod.name + to: fields.k8s.pod.name + fail_on_error: false + ignore_missing: true + - copy_fields: + fields: + - from: kubernetes.deployment.name + to: fields.k8s.workload.name + fail_on_error: false + ignore_missing: true + - add_fields: + target: _message_parser + fields: + type: logback + pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" + - condition: + equals: + kubernetes.container.name: log-gen-app-grok + config: + - type: filestream + id: fsid-${data.kubernetes.pod.name}-${data.kubernetes.container.id} + close_removed: false + clean_removed: false + paths: + - /var/log/containers/${data.kubernetes.pod.name}*${data.kubernetes.container.id}.log + parsers: + - container: + stream: all + format: auto + - multiline: + type: pattern + pattern: '^\d{4}-\d{2}-\d{2}' + negate: true + match: after + prospector.scanner.symlinks: true + processors: + - copy_fields: + fields: + - from: kubernetes.pod.name + to: fields.k8s.pod.name + fail_on_error: false + ignore_missing: true + - copy_fields: + fields: + - from: kubernetes.deployment.name + to: fields.k8s.workload.name + fail_on_error: false + ignore_missing: true + - add_fields: + target: _message_parser + fields: + type: grok + pattern: + - '%{DATESTAMP:time} %{LOGLEVEL:severity} %{WORD:class}:%{NUMBER:line} - %{GREEDYDATA:data}' + - '%{DATESTAMP_RFC2822:time} %{LOGLEVEL:severity} %{GREEDYDATA:data}' + - '%{TOMCAT_DATESTAMP:time} \| %{LOGLEVEL:level} \| %{JAVACLASS:class} - %{JAVALOGMESSAGE:logmessage}' + - '%{IP:clientIP} %{WORD:httpMethod} %{URIPATH:url}' + timestamp_field: time + timestamp_format: "yyyy-MM-dd HH:mm:ss,SSS" + - condition: + equals: + kubernetes.container.name: log-gen-app-json + config: + - type: filestream + id: fsid-${data.kubernetes.pod.name}-${data.kubernetes.container.id} + close_removed: false + clean_removed: false + paths: + - /var/log/containers/${data.kubernetes.pod.name}*${data.kubernetes.container.id}.log + parsers: + - container: + stream: all + format: auto + - multiline: + type: pattern + pattern: '^{' + negate: true + match: after + prospector.scanner.symlinks: true + processors: + - copy_fields: + fields: + - from: kubernetes.pod.name + to: fields.k8s.pod.name + fail_on_error: false + ignore_missing: true + - copy_fields: + fields: + - from: kubernetes.deployment.name + to: fields.k8s.workload.name + fail_on_error: false + ignore_missing: true + - add_fields: + target: _message_parser + fields: + type: json + timestamp_field: "@timestamp" + timestamp_pattern: "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" + - condition: + equals: + kubernetes.container.name: kube-proxy + config: + - type: filestream + id: fsid-${data.kubernetes.pod.name}-${data.kubernetes.container.id} + close_removed: false + clean_removed: false + paths: + - /var/log/containers/${data.kubernetes.pod.name}*${data.kubernetes.container.id}.log + parsers: + - container: + stream: all + format: auto + - multiline: + type: pattern + pattern: '^[a-z]|^[A-Z]' + negate: true + match: after + prospector.scanner.symlinks: true + processors: + - copy_fields: + fields: + - from: kubernetes.pod.name + to: fields.k8s.pod.name + fail_on_error: false + ignore_missing: true + - copy_fields: + fields: + - from: kubernetes.deployment.name + to: fields.k8s.workload.name + fail_on_error: false + ignore_missing: true + - add_fields: + target: _message_parser + fields: + type: infra + processors: + - add_cloud_metadata: ~ + - add_kubernetes_metadata: + in_cluster: true + host: ${NODE_NAME} + matchers: + - logs_path: + logs_path: "/var/log/containers/" + - rename: + fields: + - from: "kubernetes.namespace" + to: "kubernetes.namespace.name" + - from: "kubernetes" + to: "k8s" + - from: k8s.annotations.appdynamics.lca/filebeat.parser + to: "_message_parser" + - from: "cloud.instance.id" + to: "host.id" + ignore_missing: true + fail_on_error: false + - add_fields: + target: source + fields: + name: log-agent + - add_fields: + target: telemetry + fields: + sdk.name: log-agent + - script: + lang: javascript + source: > + function process(event) { + var podUID = event.Get("k8s.pod.uid"); + if (podUID) { + event.Put("internal.container.encapsulating_object_id", "ClusterName:" + podUID); + } + return event; + } + - drop_fields: + fields: ["agent", "stream", "ecs", "input", "orchestrator", "k8s.annotations.appdynamics", "k8s.labels", "k8s.node.labels", "cloud"] + ignore_missing: true + output.otlploggrpc: + groupby_resource_fields: + - k8s + - source + - host + - container + - log + - telemetry + - internal + - os + hosts: ["${APPD_OTELCOL_GRPC_RECEIVER_HOST}:14317"] + worker: 1 + max_bytes: 1000000 + ssl.enabled: false + ssl.supported_protocols: [TLSv1.3] + wait_for_ready: true + batch_size: 1000 + summary_debug_logs_interval: 10s + filebeat.registry.path: registry1 + filebeat.registry.file_permissions: 0640 + path.data: /opt/appdynamics/logcollector-agent/data + logging: + level: info + to_files: false + files: + path: /opt/appdynamics/logcollector-agent/log + name: lca-log + keepfiles: 5 + permissions: 0640 + selectors: [] + metrics: + enabled: false + period: 30s + monitoring: + enabled: false +appdynamics-otel-collector: + clientId: + clientSecret: + endpoint: + tokenUrl: \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/minimal-config.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/minimal-config.yaml new file mode 100644 index 00000000..c474de8d --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/minimal-config.yaml @@ -0,0 +1,27 @@ +global: + clusterName: "ClusterName" +appdynamics-cloud-k8s-monitoring: + install: + clustermon: true + defaultInfraCollectors: true + logCollector: true + logCollectorConfig: + container: + conditionalConfigs: + - condition: + operator: equals + key: kubernetes.container.name + value: + config: + multiLinePattern: '^\d{4}-\d{2}-\d{2}' + multiLineMatch: "after" + messageParser: + log4J: + enabled: true + pattern: "%d{yyyy-MM-dd'T'HH:mm:ss} %p %C{1.} [%t] %m%n" + +appdynamics-otel-collector: + clientId: + clientSecret: + endpoint: + tokenUrl: diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/minimal-default-config.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/minimal-default-config.yaml new file mode 100644 index 00000000..7a00064e --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/minimal-default-config.yaml @@ -0,0 +1,34 @@ +global: + clusterName: "ClusterName" +appdynamics-cloud-k8s-monitoring: + install: + clustermon: true + defaultInfraCollectors: true + logCollector: true + logCollectorConfig: + container: + defaultConfig: + multiLinePattern: "^{" + multiLineMatch: "after" + multiLineNegate: true + messageParser: + json: + enabled: true + conditionalConfigs: + - condition: + operator: equals + key: kubernetes.container.name + value: log-gen-app-log4j + config: + multiLinePattern: '^\d{4}-\d{2}-\d{2}' + multiLineNegate: true + multiLineMatch: "after" + messageParser: + log4J: + enabled: true + pattern: "%d{yyyy-MM-dd'T'HH:mm:ss} %p %C{1.} [%t] %m%n" + +appdynamics-otel-collector: + clientId: + clientSecret: + endpoint: diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/subparser-config.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/subparser-config.yaml new file mode 100644 index 00000000..761e4734 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/subparser-config.yaml @@ -0,0 +1,38 @@ +global: + clusterName: "ClusterName" +appdynamics-cloud-k8s-monitoring: + install: + clustermon: true + defaultInfraCollectors: true + logCollector: true +logCollectorConfig: + container: + conditionalConfigs: + - condition: + or: + - equals: + kubernetes.container.name: log-gen-app-grok-sub-win + - equals: + kubernetes.container.name: log-gen-app-grok-sub + config: + multiLinePattern: '^\d{4}-\d{2}-\d{2}' + multiLineNegate: true + multiLineMatch: "after" + messageParser: + grok: + enabled: true + patterns: + - '\[%{GREEDYDATA:log4j}\] \[%{GREEDYDATA:json}\] \[%{GREEDYDATA:log4j2}\] \[%{GREEDYDATA:logback}\] \[%{IPORHOST:grok}\] \[%{GREEDYDATA:infra}\]' + timestampPattern: "yyyy-MM-dd HH:mm:ss,SSS" + subparsers: "{\\\"parsersList\\\": [{ \\\"_message_parser.type\\\": \\\"log4j\\\", \\\"_message_parser.field\\\": \\\"log4j\\\", \\\"_message_parser.pattern\\\": \\\"%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %msg%n\\\"}, + { \\\"_message_parser.type\\\": \\\"log4j\\\", \\\"_message_parser.field\\\": \\\"log4j2\\\", \\\"_message_parser.pattern\\\": \\\"%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %msg%n\\\"}, + { \\\"_message_parser.type\\\": \\\"logback\\\", \\\"_message_parser.field\\\": \\\"logback\\\", \\\"_message_parser.pattern\\\": \\\"%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %msg%n\\\"}, + { \\\"_message_parser.type\\\": \\\"grok\\\", \\\"_message_parser.field\\\": \\\"grok\\\", \\\"_message_parser.pattern\\\": \\\"%{GREEDYDATA:infra}\\\"}, + { \\\"_message_parser.type\\\": \\\"infra\\\", \\\"_message_parser.field\\\": \\\"infra\\\"}, + { \\\"_message_parser.type\\\": \\\"json\\\", \\\"_message_parser.field\\\": \\\"json\\\", \\\"_message_parser.flatten_sep\\\": \\\"/\\\"}]\\r\\n}" + +appdynamics-otel-collector: + clientId: + clientSecret: + endpoint: + tokenUrl: \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/troubleshooting.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/troubleshooting.yaml new file mode 100644 index 00000000..37505252 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/troubleshooting.yaml @@ -0,0 +1,63 @@ +global: + clusterName: "ClusterName" +appdynamics-cloud-k8s-monitoring: + install: + clustermon: true + defaultInfraCollectors: true + logCollector: true + logCollectorConfig: + container: + conditionalConfigs: + - condition: + operator: equals + key: kubernetes.container.name + value: log-gen-app-log4j + config: + multiLinePattern: '^\d{4}-\d{2}-\d{2}' + multiLineMatch: "after" + messageParser: + log4J: + enabled: true + pattern: "%d{yyyy-MM-dd'T'HH:mm:ss} %p %C{1.} [%t] %m%n" + dropFields: ["agent", "stream", "ecs", "input", "orchestrator", "k8s.annotations.appdynamics", "k8s.labels", "k8s.node.labels", "cloud"] + batchSize: 1000 # this is the default value + maxBytes: 1000000 # this is the default value + logging: + level: info + files: + # to enable logging to files + enabled: false + # number of files to keep if logging to files is enabled + keepFiles: 5 # default value + metrics: + # to enable logging metrics data + enabled: false + period: 30s # default value + # you don't need below block if you are not using/exporting metrics + monitoring: + otlpmetric: + enabled: false + metrics: + # default metrics to capture are below + - beat.memstats.memory_alloc + - filebeat.events.active + - filebeat.harvester.running + - filebeat.harvester.skipped + - filebeat.input.log.files.truncated + - libbeat.output.read.errors + - libbeat.output.write.bytes + - libbeat.output.write.errors + - system.load.norm.5 + - system.load.norm.15 + retry: + enabled: false + ssl: + enabled: true + certificateAuthorities: ["C:/filebeat/certs/ca/ca.pem"] + certificate: "C:/filebeat/certs/client/client.pem" + key: "C:/filebeat/certs/client/client-key.pem" +appdynamics-otel-collector: + clientId: + clientSecret: + endpoint: + tokenUrl: diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/logging.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/logging.yaml new file mode 100644 index 00000000..2799d58c --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/logging.yaml @@ -0,0 +1,13 @@ +global: + clusterName: "cluster-name" + +appdynamics-otel-collector: + clientId: "id" # clientId for oauth2 extension + clientSecret: "oauth-client-secret" + tokenUrl: "https://token_ur.com/oauth2l" # tokenUrl for oauth2 extension + endpoint: "https://data.appdynamics.com" # endpoint for otlphttp exporter + configOverride: + service: + pipelines: + metrics: + exporters: [ otlphttp, logging ] \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/mtls.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/mtls.yaml new file mode 100644 index 00000000..fa5408f4 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/mtls.yaml @@ -0,0 +1,36 @@ +global: + clusterName: "cluster-name" + tls: + appdCollectors: + enabled: true + secret: + secretName: client-secret + secretKeys: + caCert: ca.crt + tlsCert: tls.crt + tlsKey: tls.key + otelReceiver: + secret: + secretName: server-secret + secretKeys: + caCert: ca.crt + tlsCert: tls.crt + tlsKey: tls.key + settings: + min_version: 1.2 + max_version: 1.3 + mtlsEnabled: true # receiver will use server CA file for mTLS to auth the client, i.e. set client_ca_file with ca.crt + + + + +appdynamics-otel-collector: + clientId: "id" # clientId for oauth2 extension + clientSecret: "oauth-client-secret" + tokenUrl: "https://token_ur.com/oauth2l" # tokenUrl for oauth2 extension + endpoint: "https://data.appdynamics.com" # endpoint for otlphttp exporter + configOverride: + service: + pipelines: + metrics: + exporters: [ otlphttp, logging ] \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/security-only.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/security-only.yaml new file mode 100644 index 00000000..54b3e099 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/security-only.yaml @@ -0,0 +1,18 @@ +appdynamics-otel-collector: + install: false + +appdynamics-cloud-k8s-monitoring: + install: + clustermon: false + defaultInfraCollectors: false + +appdynamics-otel-instrumentation: + enabled: false + +appdynamics-security-collector: + enabled: true + panoptica: + controller: + agentID: "xxxx" + secret: + sharedSecret: "xxxx" diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/simple-windows.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/simple-windows.yaml new file mode 100644 index 00000000..7bc0fe61 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/simple-windows.yaml @@ -0,0 +1,10 @@ +global: + clusterName: "cluster-name" + +appdynamics-otel-collector: + clientId: "id" # clientId for oauth2 extension + clientSecret: "oauth-client-secret" + tokenUrl: "https://token_ur.com/oauth2l" # tokenUrl for oauth2 extension + endpoint: "https://data.appdynamics.com" # endpoint for otlphttp exporter + runOn: + windows: true \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/simple.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/simple.yaml new file mode 100644 index 00000000..90551532 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/simple.yaml @@ -0,0 +1,8 @@ +global: + clusterName: "cluster-name" + +appdynamics-otel-collector: + clientId: "id" # clientId for oauth2 extension + clientSecret: "oauth-client-secret" + tokenUrl: "https://token_ur.com/oauth2l" # tokenUrl for oauth2 extension + endpoint: "https://data.appdynamics.com" # endpoint for otlphttp exporter \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/tls.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/tls.yaml new file mode 100644 index 00000000..21459de2 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/tls.yaml @@ -0,0 +1,34 @@ +global: + clusterName: "cluster-name" + tls: + appdCollectors: + enabled: true + secret: + secretName: client-secret + secretKeys: + caCert: ca.crt + tlsCert: tls.crt + tlsKey: tls.key + otelReceiver: + secret: + secretName: server-secret + secretKeys: + caCert: ca.crt + tlsCert: tls.crt + tlsKey: tls.key + settings: + min_version: 1.2 + max_version: 1.3 + + + +appdynamics-otel-collector: + clientId: "id" # clientId for oauth2 extension + clientSecret: "oauth-client-secret" + tokenUrl: "https://token_ur.com/oauth2l" # tokenUrl for oauth2 extension + endpoint: "https://data.appdynamics.com" # endpoint for otlphttp exporter + configOverride: + service: + pipelines: + metrics: + exporters: [ otlphttp, logging ] \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/tls_exporter.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/tls_exporter.yaml new file mode 100644 index 00000000..c6703c1a --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/tls_exporter.yaml @@ -0,0 +1,20 @@ +global: + clusterName: "cluster-name" + tls: + otelExporter: + secret: + secretName: client-secret + secretKeys: + tlsCert: tls.crt + tlsKey: tls.key + +appdynamics-otel-collector: + clientId: "id" # clientId for oauth2 extension + clientSecret: "oauth-client-secret" + tokenUrl: "https://token_ur.com/oauth2l" # tokenUrl for oauth2 extension + endpoint: "https://data.appdynamics.com" # endpoint for otlphttp exporter + configOverride: + service: + pipelines: + metrics: + exporters: [ otlphttp, logging ] \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/templates/NOTES.txt b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/templates/NOTES.txt new file mode 100644 index 00000000..330fb372 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/templates/NOTES.txt @@ -0,0 +1,63 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +The chart installs the following components + +1) AppDynamics OpenTelemetry Collector + +2) AppDynamics Cloud Infrastructure Collector + Enabled: {{ index .Values "appdynamics-cloud-k8s-monitoring" "install" "defaultInfraCollectors" }} + Description: Installs the Server Collector and Container Collector to monitor the host and container metrics + +3) AppDynamics Cloud Cluster Collector + Enabled: {{ index .Values "appdynamics-cloud-k8s-monitoring" "install" "clustermon" }} + Description: Installs the Cluster Collector to monitor the kubernetes metrics and events + +4) AppDynamics Cloud Log Collector + Enabled: {{ index .Values "appdynamics-cloud-k8s-monitoring" "install" "logCollector" }} + Description: Installs the Log Collector to collect the logs from applications running in kubernetes cluster + +5) AppDynamics Cloud Database Collector + Enabled: {{ index .Values "appdynamics-cloud-db-collector" "install" "dbCollector" }} + Description: Installs the DB Collector to collect metrics and monitors the Databases specified in DbConfigs + +6) Cisco Cloud Observability Network Collector + Enabled: {{ index .Values "appdynamics-network-monitoring" "enabled" }} + Description: Installs the Network Collector, to monitor network performance for applications and infrastructure +7) Appdynamics cSaaS Auto Instrumentation Agent + Enabled: {{index .Values "appdynamics-auto-instrumentation-agent" "enabled"}} + Description: Install the k8s auto instrumentation agent to instrument cSaaS entities + +7) Appdynamics cSaaS Cluster Agent + Enabled: {{ index .Values "appdynamics-csaas-k8s-cluster-agent" "installClusterAgent" }} + Description: Installs the k8s cluster agent for k8s monitoring in cSaaS controllers + +8) Appdynamics cSaaS InfraViz Agent + Enabled: {{ index .Values "appdynamics-csaas-k8s-cluster-agent" "installInfraViz" }} + Description: Installs the infraViz Agent for Infra monitoring in cSaaS controllers + +THIRD PARTY LICENSE DISCLOSURE +=============================== + +AppDynamics OpenTelemetry Collector +-------------------------------------------------- +https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/AppDynamics_Distribution_for_OpenTelemetry_Collector-2441-1714020313.pdf + +AppDynamics Cloud Cluster Collector +-------------------------------------------------- +https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/AppDynamics_Cloud_Clustermon-2440-1713545236.pdf + +AppDynamics Cloud Infrastructure Collector +-------------------------------------------------- +https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/AppDynamics_Cloud_Clustermon-2440-1713545236.pdf + +AppDynamics Cloud Log Collector +---------------------------- +https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/Appdynamics_Beats_Levitate-2440-1713840358.pdf + +AppDynamics Database Collector +---------------------------- +https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/Appdynamics_DB_Collector_Agent-242-1708958844.pdf \ No newline at end of file diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/templates/_helpers.tpl b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/templates/_helpers.tpl new file mode 100644 index 00000000..37812332 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/templates/_helpers.tpl @@ -0,0 +1,71 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "appdynamics-collectors.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "appdynamics-collectors.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "appdynamics-collectors.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "appdynamics-collectors.labels" -}} +helm.sh/chart: {{ include "appdynamics-collectors.chart" . }} +{{ include "appdynamics-collectors.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "appdynamics-collectors.selectorLabels" -}} +app.kubernetes.io/name: {{ include "appdynamics-collectors.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "appdynamics-collectors.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "appdynamics-collectors.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Service name of otel collector +*/}} +{{- define "appdynamics-collectors.otelCollectorService" -}} +{{- default "appdynamics-otel-collector-service" (index .Values "appdynamics-otel-collector" "service" "name" ) }} +{{- end }} + diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/values.yaml b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/values.yaml new file mode 100644 index 00000000..e68eb17f --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/values.yaml @@ -0,0 +1,97 @@ +global: + smartAgentInstall: false + namespace: "" + clusterName: "" + tls: + appdCollectors: + enabled: false + secret: {} + otelReceiver: + secret: {} + settings: {} + otelExporter: + secret: {} + settings: {} + helmChartVersion: 1.21.1264 +appdynamics-cloud-db-collector: + appdCloudAuth: {} + install: + dbCollector: false + dbMonitoringConfigs: false + agentManagementEnabled: true + dbCollectorPod: + image: appdynamics/appdynamics-cloud-db-collector:24.2.0-1084 + imagePullPolicy: Always + imagePullSecrets: [] + dbCollectorConfig: + pprof: + enabled : false + port : 0 + +appdynamics-cloud-k8s-monitoring: + install: + clustermon: true + defaultInfraCollectors: true + logCollector: false + + clustermonConfig: + os: linux + filters: + entity: + excludeRegex: "kube-root-ca.crt|openshift-service-ca.crt" + + servermonConfig: + os: [linux] + + containermonConfig: + os: [linux] + + clustermonPod: + image: appdynamics/appdynamics-cloud-k8s-monitoring:24.4.0-2034 + imagePullPolicy: Always + imagePullSecrets: [] + + inframonPod: + image: appdynamics/appdynamics-cloud-k8s-monitoring:24.4.0-2034 + imagePullPolicy: Always + imagePullSecrets: [] + + windowsExporterPod: + image: ghcr.io/prometheus-community/windows-exporter:0.24.0 + imagePullPolicy: Always + imagePullSecrets: [] + nodeSelector: + kubernetes.io/os: windows + + logCollectorPod: + image: appdynamics/appdynamics-cloud-log-collector-agent:24.4.0-1163 + imagePullPolicy: Always + imagePullSecrets: [] + +appdynamics-csaas-k8s-cluster-agent: + installClusterAgent: false + installInfraViz: false + +appdynamics-otel-collector: + install: true + spec: + image: appdynamics/appdynamics-cloud-otel-collector:24.4.1-1598 + mode: daemonset + imagePullPolicy: Always + +appdynamics-security-collector: + enabled: false + panoptica: + controller: + agentID: "" + secret: + sharedSecret: "" + +appdynamics-otel-instrumentation: + enabled: true + +appdynamics-network-monitoring: + enabled: false + +appdynamics-auto-instrumentation-agent: + enabled: false diff --git a/packs/appdynamics-collectors-1.21.1264/logo.png b/packs/appdynamics-collectors-1.21.1264/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1d1df3101d6e82c90297ee170e5affb460fa04cf GIT binary patch literal 47881 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 XLAmJpoR(>C00000NkvXXu0mjfwk`lp literal 0 HcmV?d00001 diff --git a/packs/appdynamics-collectors-1.21.1264/pack.json b/packs/appdynamics-collectors-1.21.1264/pack.json new file mode 100644 index 00000000..32266a44 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/pack.json @@ -0,0 +1,29 @@ +{ + "addonType": "monitoring", + "annotations": { + "ingressSupported": "false", + "source": "community", + "contributor": "appdynamics" + }, + "cloudTypes": [ + "all" + ], + "charts": [ + "charts/appdynamics-collectors-1.21.1264.tgz" + ], + "displayName": "Cisco AppDynamics Collectors", + "layer": "addon", + "name": "cisco-appdynamics-collectors", + "version": "1.21.1264", + "constraints": { + "dependencies": [ + { + "layer": "addon", + "packName": "cisco-appdynamics-operators", + "minVersion": "1.21.0", + "maxVersion": "", + "type": "required" + } + ] + } +} diff --git a/packs/appdynamics-collectors-1.21.1264/values.yaml b/packs/appdynamics-collectors-1.21.1264/values.yaml new file mode 100644 index 00000000..42fc553c --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/values.yaml @@ -0,0 +1,100 @@ +pack: + namespace: "appdynamics" + spectrocloud.com/install-priority: "1" + releaseNameOverride: + appdynamics-collectors: collector + content: + images: + - image: appdynamics/appdynamics-cloud-db-collector:24.2.0-1084 + - image: appdynamics/appdynamics-cloud-k8s-monitoring:24.4.0-2034 + - image: ghcr.io/prometheus-community/windows-exporter:0.24.0 + - image: appdynamics/appdynamics-cloud-log-collector-agent:24.4.0-1163 + - image: appdynamics/appdynamics-cloud-otel-collector:24.4.1-1598 + charts: + - repo: https://appdynamics.jfrog.io/artifactory/appdynamics-cloud-helmcharts/ + name: appdynamics-collectors + version: 1.21.1264 +charts: + appdynamics-collectors: + global: + clusterName: + oauth: + clientId: + clientSecret: + endpoint: + tokenUrl: + tls: + appdCollectors: + enabled: false + secret: {} + otelReceiver: + secret: {} + settings: {} + otelExporter: + secret: {} + settings: {} + helmChartVersion: 1.21.1264 + appdynamics-cloud-db-collector: + appdCloudAuth: {} + install: + dbCollector: false + dbMonitoringConfigs: false + dbCollectorPod: + image: appdynamics/appdynamics-cloud-db-collector:24.2.0-1084 + imagePullPolicy: Always + imagePullSecrets: [] + dbCollectorConfig: + pprof: + enabled: false + port: 0 + appdynamics-cloud-k8s-monitoring: + install: + clustermon: true + defaultInfraCollectors: true + logCollector: false + clustermonConfig: + os: linux + filters: + entity: + excludeRegex: "kube-root-ca.crt|openshift-service-ca.crt" + servermonConfig: + os: [linux] + containermonConfig: + os: [linux] + clustermonPod: + image: appdynamics/appdynamics-cloud-k8s-monitoring:24.4.0-2034 + imagePullPolicy: Always + imagePullSecrets: [] + inframonPod: + image: appdynamics/appdynamics-cloud-k8s-monitoring:24.4.0-2034 + imagePullPolicy: Always + imagePullSecrets: [] + windowsExporterPod: + image: ghcr.io/prometheus-community/windows-exporter:0.24.0 + imagePullPolicy: Always + imagePullSecrets: [] + nodeSelector: + kubernetes.io/os: windows + logCollectorPod: + image: appdynamics/appdynamics-cloud-log-collector-agent:24.4.0-1163 + imagePullPolicy: Always + imagePullSecrets: [] + appdynamics-otel-collector: + clientId: + clientSecret: + tokenUrl: + endpoint: + install: true + spec: + image: appdynamics/appdynamics-cloud-otel-collector:24.4.1-1598 + mode: daemonset + imagePullPolicy: Always + appdynamics-security-collector: + enabled: false + panoptica: + controller: + agentID: "" + secret: + sharedSecret: "" + appdynamics-otel-instrumentation: + enabled: true From 524a34bd4531f2c5aecb34857116974179b29d1d Mon Sep 17 00:00:00 2001 From: Pedro Oliveira <22790804+JPedro2@users.noreply.github.com> Date: Thu, 23 May 2024 19:12:49 +0100 Subject: [PATCH 12/22] adding elastic-stack-0.10.0 pack (#79) * adding elastic-stack pack * fixing values.yaml structure to accomodate several nested charts * adding missing content images and extra info in Presets * temp deleting APM Server Preset due to helm metadata errors * remove k8s hard dependency --------- Co-authored-by: Vishwanath S --- packs/elastic-stack-0.10.0/README.md | 63 +++++ .../charts/eck-stack-0.10.0.tgz | Bin 0 -> 28875 bytes packs/elastic-stack-0.10.0/logo.png | Bin 0 -> 5810 bytes packs/elastic-stack-0.10.0/pack.json | 29 ++ packs/elastic-stack-0.10.0/presets.yaml | 259 ++++++++++++++++++ packs/elastic-stack-0.10.0/values.yaml | 67 +++++ 6 files changed, 418 insertions(+) create mode 100644 packs/elastic-stack-0.10.0/README.md create mode 100644 packs/elastic-stack-0.10.0/charts/eck-stack-0.10.0.tgz create mode 100644 packs/elastic-stack-0.10.0/logo.png create mode 100644 packs/elastic-stack-0.10.0/pack.json create mode 100644 packs/elastic-stack-0.10.0/presets.yaml create mode 100644 packs/elastic-stack-0.10.0/values.yaml diff --git a/packs/elastic-stack-0.10.0/README.md b/packs/elastic-stack-0.10.0/README.md new file mode 100644 index 00000000..fe034bcb --- /dev/null +++ b/packs/elastic-stack-0.10.0/README.md @@ -0,0 +1,63 @@ +# Elastic Cloud on Kubernetes (ECK) + +Elastic Cloud on Kubernetes automates the deployment, provisioning, management, and orchestration of Elasticsearch, Kibana, APM Server, Enterprise Search, Beats, Elastic Agent, Elastic Maps Server, and Logstash on Kubernetes based on the operator pattern. + +Current features: + +* Elasticsearch, Kibana, APM Server, Enterprise Search, and Beats deployments +* TLS Certificates management +* Safe Elasticsearch cluster configuration & topology changes +* Persistent volumes usage +* Custom node configuration and attributes +* Secure settings keystore updates + +Supported versions: + +* Kubernetes 1.25-1.29 +* Elasticsearch, Kibana, APM Server: 6.8+, 7.1+, 8+ +* Enterprise Search: 7.7+, 8+ +* Beats: 7.0+, 8+ +* Elastic Agent: 7.10+ (standalone), 7.14+, 8+ (Fleet) +* Elastic Maps Server: 7.11+, 8+ +* Logstash 8.7+ + +Check the [Quickstart](https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-quickstart.html) to deploy your first cluster with ECK. + +For general questions, please see the Elastic [forums](https://discuss.elastic.co/c/eck). + +# ECK-Stack + +ECK Stack is a Helm chart to assist in the deployment of Elastic Stack components, which are +managed by the [ECK Operator](https://www.elastic.co/guide/en/cloud-on-k8s/current/index.html) + +## Supported Elastic Stack Resources + +The following Elastic Stack resources are currently supported. + +- Elasticsearch +- Kibana +- Elastic Agent +- Fleet Server +- Beats +- Logstash +- APM Server + +Additional resources will be supported in future releases of this Helm Chart. + +## Prerequisites + +- Kubernetes 1.21+ +- Elastic ECK Operator + +## Configuration + +The following table lists the configurable parameters of the eck-stack chart and their default values. + +| Parameter | Description | Default | +| --------- | ----------- | ------- | +| `eck-elasticsearch.enabled` | If `true`, create an Elasticsearch resource (using the eck-elasticsearch Chart) | `true` | +| `eck-kibana.enabled` | If `true`, create a Kibana resource (using the eck-kibana Chart) | `true` | +| `eck-agent.enabled` | If `true`, create an Elastic Agent resource (using the eck-agent Chart) | `false` | +| `eck-fleet-server.enabled` | If `true`, create a Fleet Server resource (using the eck-fleet-server Chart) | `false` | +| `eck-logstash.enabled` | If `true`, create a Logstash resource (using the eck-logstash Chart) | `false` | +| `eck-apm-server.enabled` | If `true`, create a standalone Elastic APM Server resource (using the eck-apm-server Chart) | `false` | diff --git a/packs/elastic-stack-0.10.0/charts/eck-stack-0.10.0.tgz b/packs/elastic-stack-0.10.0/charts/eck-stack-0.10.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..cf843490c7334040974df4229434b13549c26c2c GIT binary patch literal 28875 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 literal 0 HcmV?d00001 diff --git a/packs/elastic-stack-0.10.0/logo.png b/packs/elastic-stack-0.10.0/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fa70b78daa45585ec0f802dfe637e4ce2172d6f8 GIT binary patch literal 5810 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 /data/logstash-tutorial.log"] + volumeMounts: + - name: data + mountPath: /data + containers: + - name: filebeat + securityContext: + runAsUser: 1000 + volumeMounts: + - name: data + mountPath: /data + - name: beat-data + mountPath: /usr/share/filebeat/data + volumes: + - name: data + emptydir: {} + - name: beat-data + emptydir: {} + eck-logstash: + enabled: true + # This is required to be able to set the logstash + # output of beats in a consistent manner. + fullnameOverride: "logstash-ls-beats" + elasticsearchRefs: + # This clusterName is required to match the environment variables + # used in the below config.string output section. + - clusterName: eck + name: elasticsearch + pipelines: + - pipeline.id: main + config.string: | + input { + beats { + port => 5044 + } + } + filter { + grok { + match => { "message" => "%{HTTPD_COMMONLOG}"} + } + geoip { + source => "[source][address]" + target => "[source]" + } + } + output { + elasticsearch { + hosts => [ "${ECK_ES_HOSTS}" ] + user => "${ECK_ES_USER}" + password => "${ECK_ES_PASSWORD}" + ssl_certificate_authorities => "${ECK_ES_SSL_CERTIFICATE_AUTHORITY}" + } + } + services: + - name: beats + service: + spec: + type: ClusterIP + ports: + - port: 5044 + name: "filebeat" + protocol: TCP + targetPort: 5044 \ No newline at end of file diff --git a/packs/elastic-stack-0.10.0/values.yaml b/packs/elastic-stack-0.10.0/values.yaml new file mode 100644 index 00000000..78039b89 --- /dev/null +++ b/packs/elastic-stack-0.10.0/values.yaml @@ -0,0 +1,67 @@ +# Default values for eck-elastic-operator +# This is a YAML-formatted file +pack: + content: + images: + - image: docker.elastic.co/kibana/kibana:8.13.0 + - image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0 + - image: docker.elastic.co/logstash/logstash:8.13.0 + - image: docker.elastic.co/beats/filebeat:8.13.0 + - image: docker.io/curlimages/curl + + + charts: + - repo: https://helm.elastic.co/ + name: eck-stack + version: 0.10.0 + #The namespace (on the target cluster) to install this chart + #When not found, a new namespace will be created + namespace: "elastic-stack" + +charts: + eck-stack: + # Default values for eck-stack. + # This is a YAML-formatted file. + + # If enabled, will use the eck-elasticsearch chart and deploy an Elasticsearch resource. + # + eck-elasticsearch: + enabled: true + # This is adjusting the full name of the elasticsearch resource so that both the eck-elasticsearch + # and the eck-kibana chart work together by default in the eck-stack chart. + fullnameOverride: elasticsearch + + # If enabled, will use the eck-kibana chart and deploy a Kibana resource. + # + eck-kibana: + enabled: true + spec: + # This is also adjusting the kibana reference to the elasticsearch resource named previously so that + # both the eck-elasticsearch and the eck-kibana chart work together by default in the eck-stack chart. + elasticsearchRef: + name: elasticsearch + + # If enabled, will use the eck-agent chart and deploy an Elastic Agent instance. + # + eck-agent: + enabled: false + + # If enabled, will use the eck-fleet-server chart and deploy a Fleet Server resource. + # + eck-fleet-server: + enabled: false + + # If enabled, will use the eck-beats chart and deploy a Beats resource. + # + eck-beats: + enabled: false + + # If enabled, will use the eck-logstash chart and deploy a Logstash resource. + # + eck-logstash: + enabled: false + + # If enabled, will use the eck-apm-server chart and deploy a standalone APM Server resource. + # + eck-apm-server: + enabled: false \ No newline at end of file From aa660600e120608871e144b3e9532aed5926f1c6 Mon Sep 17 00:00:00 2001 From: Pedro Oliveira <22790804+JPedro2@users.noreply.github.com> Date: Thu, 23 May 2024 19:14:44 +0100 Subject: [PATCH 13/22] adding elastic-operator-2.12.1 pack (#78) * adding elastic-operator pack * removing k8s version hard dependency and fixing chart structure * adding missing eck-operator chart --------- Co-authored-by: Vishwanath S --- packs/elastic-operator-2.12.1/README.md | 43 +++ .../charts/eck-operator-2.12.1.tgz | Bin 0 -> 131186 bytes packs/elastic-operator-2.12.1/logo.png | Bin 0 -> 5810 bytes packs/elastic-operator-2.12.1/pack.json | 18 + packs/elastic-operator-2.12.1/values.yaml | 355 ++++++++++++++++++ 5 files changed, 416 insertions(+) create mode 100644 packs/elastic-operator-2.12.1/README.md create mode 100644 packs/elastic-operator-2.12.1/charts/eck-operator-2.12.1.tgz create mode 100644 packs/elastic-operator-2.12.1/logo.png create mode 100644 packs/elastic-operator-2.12.1/pack.json create mode 100644 packs/elastic-operator-2.12.1/values.yaml diff --git a/packs/elastic-operator-2.12.1/README.md b/packs/elastic-operator-2.12.1/README.md new file mode 100644 index 00000000..ee0b2ca6 --- /dev/null +++ b/packs/elastic-operator-2.12.1/README.md @@ -0,0 +1,43 @@ +# Elastic Cloud on Kubernetes (ECK) + +Elastic Cloud on Kubernetes automates the deployment, provisioning, management, and orchestration of Elasticsearch, Kibana, APM Server, Enterprise Search, Beats, Elastic Agent, Elastic Maps Server, and Logstash on Kubernetes based on the operator pattern. + +Current features: + +* Elasticsearch, Kibana, APM Server, Enterprise Search, and Beats deployments +* TLS Certificates management +* Safe Elasticsearch cluster configuration & topology changes +* Persistent volumes usage +* Custom node configuration and attributes +* Secure settings keystore updates + +Supported versions: + +* Kubernetes 1.25-1.29 +* Elasticsearch, Kibana, APM Server: 6.8+, 7.1+, 8+ +* Enterprise Search: 7.7+, 8+ +* Beats: 7.0+, 8+ +* Elastic Agent: 7.10+ (standalone), 7.14+, 8+ (Fleet) +* Elastic Maps Server: 7.11+, 8+ +* Logstash 8.7+ + +Check the [Quickstart](https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-quickstart.html) to deploy your first cluster with ECK. + +For general questions, please see the Elastic [forums](https://discuss.elastic.co/c/eck). + +# ECK Operator Helm Chart + +A Helm chart to install the ECK Operator: the official Kubernetes operator from Elastic to orchestrate Elasticsearch, Kibana, APM Server, Enterprise Search, and Beats on Kubernetes. + +For more information about the ECK Operator, see: +- [Documentation](https://www.elastic.co/guide/en/cloud-on-k8s/current/index.html) +- [GitHub repo](https://github.com/elastic/cloud-on-k8s) + + +## Requirements + +- Supported Kubernetes versions are listed in the documentation: https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s_supported_versions.html + +## Usage + +Refer to the documentation at https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-install-helm.html \ No newline at end of file diff --git a/packs/elastic-operator-2.12.1/charts/eck-operator-2.12.1.tgz b/packs/elastic-operator-2.12.1/charts/eck-operator-2.12.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..99f291768cc344eb028996ae41041fb55181a19e GIT binary patch literal 131186 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%0Au1tC9n^07d7}UwYlQDt1NF^n3LeRl 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%0A8rb{>b)CaCM8 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 iU&DU{UiSPvKhMwe^ZcYg|6c$A0RR6q!81Vs>) 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 Date: Thu, 23 May 2024 19:32:44 +0100 Subject: [PATCH 14/22] adding strimzi-kafka-0.40.0 pack (#77) * adding strimzi-kafka pack * fixing chart structure and removing k8s hard dependency --------- Co-authored-by: Vishwanath S --- packs/strimzi-kafka-operator-0.40.0/README.md | 190 ++++++++++++++++ ...mzi-kafka-operator-helm-3-chart-0.40.0.tgz | Bin 0 -> 124903 bytes packs/strimzi-kafka-operator-0.40.0/logo.png | Bin 0 -> 22288 bytes packs/strimzi-kafka-operator-0.40.0/pack.json | 18 ++ .../strimzi-kafka-operator-0.40.0/values.yaml | 210 ++++++++++++++++++ 5 files changed, 418 insertions(+) create mode 100644 packs/strimzi-kafka-operator-0.40.0/README.md create mode 100644 packs/strimzi-kafka-operator-0.40.0/charts/strimzi-kafka-operator-helm-3-chart-0.40.0.tgz create mode 100644 packs/strimzi-kafka-operator-0.40.0/logo.png create mode 100644 packs/strimzi-kafka-operator-0.40.0/pack.json create mode 100644 packs/strimzi-kafka-operator-0.40.0/values.yaml diff --git a/packs/strimzi-kafka-operator-0.40.0/README.md b/packs/strimzi-kafka-operator-0.40.0/README.md new file mode 100644 index 00000000..8504816c --- /dev/null +++ b/packs/strimzi-kafka-operator-0.40.0/README.md @@ -0,0 +1,190 @@ +# Strimzi: Apache Kafka on Kubernetes + +Strimzi provides a way to run an [Apache Kafka®](https://kafka.apache.org) cluster on +[Kubernetes](https://kubernetes.io/) in various deployment configurations. + +See their [website](https://strimzi.io) for more details about the project. + +**!!! IMPORTANT !!!** +From Strimzi 0.40 on, we support only Kubernetes 1.23 and newer. +Kubernetes versions 1.21 and 1.22 are no longer supported. + +## Introduction + +This chart bootstraps the Strimzi Cluster Operator Deployment, Cluster Roles, Cluster Role Bindings, Service Accounts, and +Custom Resource Definitions for running [Apache Kafka](https://kafka.apache.org/) on [Kubernetes](http://kubernetes.io) +cluster using the [Helm](https://helm.sh) package manager. + +### Supported Features + +* **Manages the Kafka Cluster** - Deploys and manages all of the components of this complex application, including dependencies like Apache ZooKeeper® that are traditionally hard to administer. +* **Includes Kafka Connect** - Allows for configuration of common data sources and sinks to move data into and out of the Kafka cluster. +* **Topic Management** - Creates and manages Kafka Topics within the cluster. +* **User Management** - Creates and manages Kafka Users within the cluster. +* **Connector Management** - Creates and manages Kafka Connect connectors. +* **Includes Kafka Mirror Maker 1 and 2** - Allows for mirroring data between different Apache Kafka® clusters. +* **Includes HTTP Kafka Bridge** - Allows clients to send and receive messages through an Apache Kafka® cluster via the HTTP protocol. +* **Includes Cruise Control** - Automates the process of balancing partitions across an Apache Kafka® cluster. +* **Prometheus monitoring** - Built-in support for monitoring using Prometheus. +* **Grafana Dashboards** - Built-in support for loading Grafana® dashboards via the grafana_sidecar + +### Upgrading your Clusters + +To upgrade the Strimzi operator, you can use the `helm upgrade` command. +The `helm upgrade` command does not upgrade the [Custom Resource Definitions](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/). +Install the new CRDs manually after upgrading the Cluster Operator. +You can access the CRDs from our [GitHub release page](https://github.com/strimzi/strimzi-kafka-operator/releases) or find them in the `crd` subdirectory inside the Helm Chart. + +The Strimzi Operator understands how to run and upgrade between a set of Kafka versions. +When specifying a new version in your config, check to make sure you aren't using any features that may have been removed. +See [the upgrade guide](https://strimzi.io/docs/operators/latest/deploying.html#assembly-upgrading-kafka-versions-str) for more information. + +## Prerequisites + +- Kubernetes 1.23+ + +## Configuration + +The following table lists the configurable parameters of the Strimzi chart and their default values. Runtime +configuration of Kafka and other components are defined within their respective Custom Resource Definitions. See +the documentation for more details. + +| Parameter | Description | Default | +|---------------------------------------------|---------------------------------------------------------------------------------|------------------------------| +| `replicas` | Number of replicas of the cluster operator | 1 | +| `watchNamespaces` | Comma separated list of additional namespaces for the strimzi-operator to watch | [] | +| `watchAnyNamespace` | Watch the whole Kubernetes cluster (all namespaces) | `false` | +| `defaultImageRegistry` | Default image registry for all the images | `quay.io` | +| `defaultImageRepository` | Default image registry for all the images | `strimzi` | +| `defaultImageTag` | Default image tag for all the images except Kafka Bridge | `0.40.0` | +| `image.registry` | Override default Cluster Operator image registry | `nil` | +| `image.repository` | Override default Cluster Operator image repository | `nil` | +| `image.name` | Cluster Operator image name | `cluster-operator` | +| `image.tag` | Override default Cluster Operator image tag | `nil` | +| `image.digest` | Override Cluster Operator image tag with digest | `nil` | +| `image.imagePullPolicy` | Image pull policy for all pods deployed by Cluster Operator | `IfNotPresent` | +| `image.imagePullSecrets` | List of Docker registry pull secrets | `[]` | +| `fullReconciliationIntervalMs` | Full reconciliation interval in milliseconds | 120000 | +| `leaderElection.enable` | Whether to enable leader election | `true` | +| `operationTimeoutMs` | Operation timeout in milliseconds | 300000 | +| `operatorNamespaceLabels` | Labels of the namespace where the operator runs | `nil` | +| `podSecurityContext` | Cluster Operator pod's security context | `nil` | +| `priorityClassName` | Cluster Operator pod's priority class name | `nil` | +| `securityContext` | Cluster Operator container's security context | `nil` | +| `rbac.create` | Whether to create RBAC related resources | `yes` | +| `serviceAccountCreate` | Whether to create a service account | `yes` | +| `serviceAccount` | Cluster Operator's service account | `strimzi-cluster-operator` | +| `podDisruptionBudget.enabled` | Whether to enable the podDisruptionBudget feature | `false` | +| `podDisruptionBudget.minAvailable` | Default value for how many pods must be running in a cluster | `1` | +| `podDisruptionBudget.maxUnavailable` | Default value for how many pods can be down | `nil` | +| `extraEnvs` | Extra environment variables for the Cluster operator container | `[]` | +| `kafka.image.registry` | Override default Kafka image registry | `nil` | +| `kafka.image.repository` | Override default Kafka image repository | `nil` | +| `kafka.image.name` | Kafka image name | `kafka` | +| `kafka.image.tagPrefix` | Override default Kafka image tag prefix | `nil` | +| `kafka.image.tag` | Override default Kafka image tag and ignore suffix | `nil` | +| `kafka.image.digest` | Override Kafka image tag with digest | `nil` | +| `kafkaConnect.image.registry` | Override default Kafka Connect image registry | `nil` | +| `kafkaConnect.image.repository` | Override default Kafka Connect image repository | `nil` | +| `kafkaConnect.image.name` | Kafka Connect image name | `kafka` | +| `kafkaConnect.image.tagPrefix` | Override default Kafka Connect image tag prefix | `nil` | +| `kafkaConnect.image.tag` | Override default Kafka Connect image tag and ignore suffix | `nil` | +| `kafkaConnect.image.digest` | Override Kafka Connect image tag with digest | `nil` | +| `kafkaMirrorMaker.image.registry` | Override default Kafka Mirror Maker image registry | `nil` | +| `kafkaMirrorMaker.image.repository` | Override default Kafka Mirror Maker image repository | `nil` | +| `kafkaMirrorMaker.image.name` | Kafka Mirror Maker image name | `kafka` | +| `kafkaMirrorMaker.image.tagPrefix` | Override default Kafka Mirror Maker image tag prefix | `nil` | +| `kafkaMirrorMaker.image.tag` | Override default Kafka Mirror Maker image tag and ignore suffix | `nil` | +| `kafkaMirrorMaker.image.digest` | Override Kafka Mirror Maker image tag with digest | `nil` | +| `cruiseControl.image.registry` | Override default Cruise Control image registry | `nil` | +| `cruiseControl.image.repository` | Override default Cruise Control image repository | `nil` | +| `cruiseControl.image.name` | Cruise Control image name | `kafka` | +| `cruiseControl.image.tagPrefix` | Override default Cruise Control image tag prefix | `nil` | +| `cruiseControl.image.tag` | Override default Cruise Control image tag and ignore suffix | `nil` | +| `cruiseControl.image.digest` | Override Cruise Control image tag with digest | `nil` | +| `topicOperator.image.registry` | Override default Topic Operator image registry | `nil` | +| `topicOperator.image.repository` | Override default Topic Operator image repository | `nil` | +| `topicOperator.image.name` | Topic Operator image name | `operator` | +| `topicOperator.image.tag` | Override default Topic Operator image tag | `nil` | +| `topicOperator.image.digest` | Override Topic Operator image tag with digest | `nil` | +| `userOperator.image.registry` | Override default User Operator image registry | `nil` | +| `userOperator.image.repository` | Override default User Operator image repository | `nil` | +| `userOperator.image.name` | User Operator image name | `operator` | +| `userOperator.image.tag` | Override default User Operator image tag | `nil` | +| `userOperator.image.digest` | Override User Operator image tag with digest | `nil` | +| `kafkaInit.image.registry` | Override default Init Kafka image registry | `nil` | +| `kafkaInit.image.repository` | Override default Init Kafka image repository | `nil` | +| `kafkaInit.image.name` | Init Kafka image name | `operator` | +| `kafkaInit.image.tag` | Override default Init Kafka image tag | `nil` | +| `kafkaInit.image.digest` | Override Init Kafka image tag with digest | `nil` | +| `tlsSidecarEntityOperator.image.registry` | Override default TLS Sidecar Entity Operator image registry | `nil` | +| `tlsSidecarEntityOperator.image.repository` | Override default TLS Sidecar Entity Operator image repository | `nil` | +| `tlsSidecarEntityOperator.image.name` | TLS Sidecar Entity Operator image name | `kafka` | +| `tlsSidecarEntityOperator.image.tagPrefix` | Override default TLS Sidecar Entity Operator image tag prefix | `nil` | +| `tlsSidecarEntityOperator.image.tag` | Override default TLS Sidecar Entity Operator image tag and ignore suffix | `nil` | +| `tlsSidecarEntityOperator.image.digest` | Override TLS Sidecar Entity Operator image tag with digest | `nil` | +| `kafkaBridge.image.registry` | Override default Kafka Bridge image registry | `quay.io` | +| `kafkaBridge.image.repository` | Override default Kafka Bridge image repository | `strimzi` | +| `kafkaBridge.image.name` | Kafka Bridge image name | `kafka-bridge` | +| `kafkaBridge.image.tag` | Override default Kafka Bridge image tag | `0.28.0` | +| `kafkaBridge.image.digest` | Override Kafka Bridge image tag with digest | `nil` | +| `kafkaExporter.image.registry` | Override default Kafka Exporter image registry | `nil` | +| `kafkaExporter.image.repository` | Override default Kafka Exporter image repository | `nil` | +| `kafkaExporter.image.name` | Kafka Exporter image name | `kafka` | +| `kafkaExporter.image.tagPrefix` | Override default Kafka Exporter image tag prefix | `nil` | +| `kafkaExporter.image.tag` | Override default Kafka Exporter image tag and ignore suffix | `nil` | +| `kafkaExporter.image.digest` | Override Kafka Exporter image tag with digest | `nil` | +| `kafkaMirrorMaker2.image.registry` | Override default Kafka Mirror Maker 2 image registry | `nil` | +| `kafkaMirrorMaker2.image.repository` | Override default Kafka Mirror Maker 2 image repository | `nil` | +| `kafkaMirrorMaker2.image.name` | Kafka Mirror Maker 2 image name | `kafka` | +| `kafkaMirrorMaker2.image.tagPrefix` | Override default Kafka Mirror Maker 2 image tag prefix | `nil` | +| `kafkaMirrorMaker2.image.tag` | Override default Kafka Mirror Maker 2 image tag and ignore suffix | `nil` | +| `kafkaMirrorMaker2.image.digest` | Override Kafka Mirror Maker 2 image tag with digest | `nil` | +| `kanikoExecutor.image.registry` | Override default Kaniko Executor image registry | `nil` | +| `kanikoExecutor.image.repository` | Override default Kaniko Executor image repository | `nil` | +| `kanikoExecutor.image.name` | Kaniko Executor image name | `kaniko-executor` | +| `kanikoExecutor.image.tag` | Override default Kaniko Executor image tag | `nil` | +| `kanikoExecutor.image.digest` | Override Kaniko Executor image tag with digest | `nil` | +| `resources.limits.memory` | Memory constraint for limits | `256Mi` | +| `resources.limits.cpu` | CPU constraint for limits | `1000m` | +| `resources.requests.memory` | Memory constraint for requests | `256Mi` | +| `livenessProbe.initialDelaySeconds` | Liveness probe initial delay in seconds | 10 | +| `livenessProbe.periodSeconds` | Liveness probe period in seconds | 30 | +| `readinessProbe.initialDelaySeconds` | Readiness probe initial delay in seconds | 10 | +| `readinessProbe.periodSeconds` | Readiness probe period in seconds | 30 | +| `imageTagOverride` | Override all image tag config | `nil` | +| `createGlobalResources` | Allow creation of cluster-scoped resources | `true` | +| `createAggregateRoles` | Create cluster roles that extend aggregated roles to use Strimzi CRDs | `false` | +| `tolerations` | Add tolerations to Operator Pod | `[]` | +| `affinity` | Add affinities to Operator Pod | `{}` | +| `annotations` | Add annotations to Operator Pod | `{}` | +| `labels` | Add labels to Operator Pod | `{}` | +| `nodeSelector` | Add a node selector to Operator Pod | `{}` | +| `featureGates` | Feature Gates configuration | `nil` | +| `tmpDirSizeLimit` | Set the `sizeLimit` for the tmp dir volume used by the operator | `1Mi` | +| `labelsExclusionPattern` | Override the exclude pattern for exclude some labels | `""` | +| `generateNetworkPolicy` | Controls whether Strimzi generates network policy resources | `true` | +| `connectBuildTimeoutMs` | Overrides the default timeout value for building new Kafka Connect | `300000` | +| `mavenBuilder.image.registry` | Override default Maven Builder image registry | `nil` | +| `mavenBuilder.image.repository` | Maven Builder image repository | `nil` | +| `mavenBuilder.image.name` | Override default Maven Builder image name | `maven-builder` | +| `mavenBuilder.image.tag` | Override default Maven Builder image tag | `nil` | +| `mavenBuilder.image.digest` | Override Maven Builder image tag with digest | `nil` | +| `logConfiguration` | Override default `log4j.properties` content | `nil` | +| `dashboards.enable` | Generate configmaps containing the dashboards | `false` | +| `dashboards.label` | How should the dashboards be labeled for the sidecar | `grafana_dashboard` | +| `dashboards.labelValue` | What should the dashboards label value be for the sidecar | `"1"` | +| `dashboards.extraLabels` | Any additional labels you would like on the dashboards | `{}` | +| `dashboards.namespace` | What namespace should the dashboards be loaded into | `Follows toplevel Namespace` | +| `dashboards.annotations` | Any custom annotations (such as folder for the sidecar) | `{}` | + +### Getting help + +If you encounter any issues while using Strimzi, you can get help using: +* [Strimzi mailing list on CNCF](https://lists.cncf.io/g/cncf-strimzi-users/topics) +* [Strimzi Slack channel on CNCF workspace](https://cloud-native.slack.com/messages/strimzi) +* [GitHub Discussions](https://github.com/strimzi/strimzi-kafka-operator/discussions) + +### License + +Strimzi is licensed under the [Apache License, Version 2.0](https://github.com/strimzi/strimzi-kafka-operator/blob/main/LICENSE). \ No newline at end of file diff --git a/packs/strimzi-kafka-operator-0.40.0/charts/strimzi-kafka-operator-helm-3-chart-0.40.0.tgz b/packs/strimzi-kafka-operator-0.40.0/charts/strimzi-kafka-operator-helm-3-chart-0.40.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..d7dd55448b418769ee66bfa2478b68a3e24f2952 GIT binary patch literal 124903 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 vYL>eL5|AD*aM2yJQKnJ+d#!p5E^Qgg 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%0ARmJ9DL+F)mM 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 literal 0 HcmV?d00001 diff --git a/packs/strimzi-kafka-operator-0.40.0/logo.png b/packs/strimzi-kafka-operator-0.40.0/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8c0ff2892216011fbcdef34d38fce57a81d8cf40 GIT binary patch literal 22288 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 Cpa; Date: Fri, 24 May 2024 08:52:54 +0200 Subject: [PATCH 15/22] feat: unCtl v1.1.0 pack (#75) * feat: new version of unctl * fix: values section * chore: created schema for token --- packs/unctl-1.1.0/README.md | 51 ++++++++ packs/unctl-1.1.0/charts/unctl-1.1.0.tgz | Bin 0 -> 3572 bytes packs/unctl-1.1.0/charts/unctl/Chart.yaml | 15 +++ .../charts/unctl/templates/NOTES.txt | 4 + .../charts/unctl/templates/_helpers.tpl | 41 ++++++ .../charts/unctl/templates/ai.secret.yaml | 9 ++ .../charts/unctl/templates/clusterrole.yaml | 108 ++++++++++++++++ .../unctl/templates/clusterrolebinding.yaml | 19 +++ .../charts/unctl/templates/cronjob.yaml | 26 ++++ .../charts/unctl/templates/deployment.yaml | 121 ++++++++++++++++++ .../charts/unctl/templates/job.yaml | 33 +++++ .../charts/unctl/templates/service.yaml | 21 +++ .../charts/unctl/templates/servieaccount.yaml | 11 ++ packs/unctl-1.1.0/charts/unctl/values.yaml | 68 ++++++++++ packs/unctl-1.1.0/logo.png | Bin 0 -> 121080 bytes packs/unctl-1.1.0/pack.json | 17 +++ packs/unctl-1.1.0/schema.yaml | 2 + packs/unctl-1.1.0/values.yaml | 81 ++++++++++++ 18 files changed, 627 insertions(+) create mode 100644 packs/unctl-1.1.0/README.md create mode 100644 packs/unctl-1.1.0/charts/unctl-1.1.0.tgz create mode 100644 packs/unctl-1.1.0/charts/unctl/Chart.yaml create mode 100644 packs/unctl-1.1.0/charts/unctl/templates/NOTES.txt create mode 100644 packs/unctl-1.1.0/charts/unctl/templates/_helpers.tpl create mode 100644 packs/unctl-1.1.0/charts/unctl/templates/ai.secret.yaml create mode 100644 packs/unctl-1.1.0/charts/unctl/templates/clusterrole.yaml create mode 100644 packs/unctl-1.1.0/charts/unctl/templates/clusterrolebinding.yaml create mode 100644 packs/unctl-1.1.0/charts/unctl/templates/cronjob.yaml create mode 100644 packs/unctl-1.1.0/charts/unctl/templates/deployment.yaml create mode 100644 packs/unctl-1.1.0/charts/unctl/templates/job.yaml create mode 100644 packs/unctl-1.1.0/charts/unctl/templates/service.yaml create mode 100644 packs/unctl-1.1.0/charts/unctl/templates/servieaccount.yaml create mode 100644 packs/unctl-1.1.0/charts/unctl/values.yaml create mode 100644 packs/unctl-1.1.0/logo.png create mode 100644 packs/unctl-1.1.0/pack.json create mode 100644 packs/unctl-1.1.0/schema.yaml create mode 100644 packs/unctl-1.1.0/values.yaml diff --git a/packs/unctl-1.1.0/README.md b/packs/unctl-1.1.0/README.md new file mode 100644 index 00000000..27c90384 --- /dev/null +++ b/packs/unctl-1.1.0/README.md @@ -0,0 +1,51 @@ +# unCtl + +The **unCtl** kubernetes operator to run various checks on the cluster's resources. It is based on [unCtl cli tool](https://docs.unskript.com/unctl) and provides API and web interface wrapper for you reports. + + +## Prerequisites + +1. Kubernetes cluster version 1.19 or higher with `linux/amd64` architecture. + +2. Support of `LoadBalancer` service type in your cluster. This service type is typically available natively in cloud environments. However, in on-premises and edge computing environments, additional steps may be required to support it. If `LoadBalancer` support is not available, set `service.loadbalancer` to `false` in your values file and consider alternative methods to expose the web interface. + + +## Parameters + +To deploy the unctl operator, you need to set, at minimum, the following parameters in the pack's YAML. + +| Name | Description | Type | Default Value | Required | +| --- | --- | --- | --- | --- | +| `frontend.enabled` | Defines whether it should create web interface container. | Boolean | true | Yes | +| `schedule` | Schedule to scan cluster resources. Default is 12 AM every day. | String | 0 0 * * * | Yes | +| `namespaces` | List of namespaces to conduct checks on. | Array | [] | Yes | +| `service.enabled` | Defines whether it should create service. | Boolean | true | Yes | +| `service.loadbalancer` | Defines whether it service should be a `LoadBalancer` type. | Boolean | true | Yes | +| `service.port` | Port exposed by service. | Integer | 8000 | Yes | + + +Look at the [values file](./values.yaml) for more information. + +## Usage + +- **Which checks were carried out** + + In current version all checks are performed. Look at [K8S unctl checks](https://docs.unskript.com/unctl/overview/health-checks/kubernetes) for individual checks information. + +- **When the checks are being executed** + + Once operator installed in your cluster it will automatically initiate checks execution. + Additionaly based on `schedule` value it will run checks on regular basis. + +- **How to view report** + + Open `unctl` service in the Pallete or find exposed address in your `LoadBalancer` service. + + You can view last available report. + + +## References + +- [unCtl Documentation](https://docs.unskript.com/unctl) +- [Public unCtl Health Checks github](https://github.com/unctl-sh/unctl) +- [Official website](https://unskript.com/) \ No newline at end of file diff --git a/packs/unctl-1.1.0/charts/unctl-1.1.0.tgz b/packs/unctl-1.1.0/charts/unctl-1.1.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..e7e5fb4c49979ba1a8d0f482317cfec1d4e689c7 GIT binary patch literal 3572 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 + curl -X POST "http://{{ template "unctl.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.port }}/api/v1/executions" -H 'accept: application/json' -H 'Content-Type: application/json' -d '{}' + restartPolicy: OnFailure diff --git a/packs/unctl-1.1.0/charts/unctl/templates/deployment.yaml b/packs/unctl-1.1.0/charts/unctl/templates/deployment.yaml new file mode 100644 index 00000000..bd15d377 --- /dev/null +++ b/packs/unctl-1.1.0/charts/unctl/templates/deployment.yaml @@ -0,0 +1,121 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: {{ template "unctl.name" . }} + chart: {{ template "unctl.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + name: {{ template "unctl.fullname" . }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ template "unctl.name" . }} + release: {{ .Release.Name }} + template: + metadata: + annotations: + {{- if .Values.podAnnotations }} +{{ toYaml .Values.podAnnotations | indent 8 }} + {{- end }} + labels: + app: {{ template "unctl.name" . }} + release: {{ .Release.Name }} + chart: {{ template "unctl.chart" . }} + {{- if .Values.podLabels }} +{{ toYaml .Values.podLabels | indent 8 }} + {{- end }} + spec: + containers: + - name: {{ template "unctl.name" . }} + image: {{ printf "%s/%s:%s" .Values.image.registry .Values.image.api .Values.image.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: api + protocol: TCP + containerPort: 8000 + env: + - name: RETENTION_PERIOD + value: "{{ .Values.retention_period }}" + - name: NAMESPACES_TO_CHECK + value: "{{ .Values.namespaces | join "," }}" + - name: AI_ENABLED + value: "{{ (.Values.ai).enabled | default "false" }}" + {{- if and (.Values.ai) (.Values.ai.enabled) }} + {{- if .Values.ai.token }} + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: {{ template "unctl.fullname" . }}-ai-secret + key: token + {{- end }} + - name: LLM_PROVIDER + value: "{{ .Values.ai.provider | default "OpenAI" }}" + {{- if .Values.ai.config }} + - name: LLM_MODEL_NAME + value: "{{ .Values.ai.config.model | default "gpt-4" }}" + - name: LLM_PROVIDER_ENDPOINT + value: "{{ .Values.ai.config.host }}" + {{- end }} + {{- end }} + livenessProbe: + httpGet: + path: /openapi.json + port: 8000 + initialDelaySeconds: 15 + timeoutSeconds: 2 + periodSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /openapi.json + port: 8000 + initialDelaySeconds: 5 + timeoutSeconds: 2 + periodSeconds: 5 + failureThreshold: 1 + resources: +{{ toYaml .Values.resources | indent 10 }} + {{- if .Values.frontend.enabled }} + - name: {{ template "unctl.name" . }}-frontend + image: {{ printf "%s/%s:%s" .Values.image.registry .Values.image.frontend .Values.image.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + protocol: TCP + containerPort: 3000 + env: + - name: AI_ENABLED + value: "{{ (.Values.ai).enabled | default "false" }}" + livenessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 15 + timeoutSeconds: 2 + periodSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 5 + timeoutSeconds: 2 + periodSeconds: 5 + failureThreshold: 1 + resources: +{{ toYaml .Values.resources | indent 10 }} + {{- end }} + {{- if .Values.affinity }} + affinity: +{{ toYaml .Values.affinity | indent 8 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 8 }} + {{- end }} + serviceAccountName: {{ template "unctl.serviceAccountName" . }} + tolerations: +{{ toYaml .Values.tolerations | indent 8 }} + restartPolicy: Always diff --git a/packs/unctl-1.1.0/charts/unctl/templates/job.yaml b/packs/unctl-1.1.0/charts/unctl/templates/job.yaml new file mode 100644 index 00000000..3cca28fa --- /dev/null +++ b/packs/unctl-1.1.0/charts/unctl/templates/job.yaml @@ -0,0 +1,33 @@ +apiVersion: batch/v1 +kind: Job +metadata: + labels: + app: {{ template "unctl.name" . }} + chart: {{ template "unctl.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + name: {{ template "unctl.fullname" . }}-job + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "5" +spec: + template: + spec: + containers: + - name: curl-container + image: curlimages/curl:latest + command: ["/bin/sh", "-c"] + args: + - | + set -e + echo "Waiting for 1 minute..." + sleep 60 + echo "Checking if unctl service is ready..." + until curl -f -s http://{{ template "unctl.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.port }}/docs; do + echo "Waiting for unctl service..." + sleep 5 + done + echo "unctl is ready, proceeding to make the execution call" + curl -X POST "http://{{ template "unctl.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.port }}/api/v1/executions" -H 'accept: application/json' -H 'Content-Type: application/json' -d '{}' + restartPolicy: Never + backoffLimit: 10 diff --git a/packs/unctl-1.1.0/charts/unctl/templates/service.yaml b/packs/unctl-1.1.0/charts/unctl/templates/service.yaml new file mode 100644 index 00000000..37d6451e --- /dev/null +++ b/packs/unctl-1.1.0/charts/unctl/templates/service.yaml @@ -0,0 +1,21 @@ +{{- if .Values.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ template "unctl.name" . }} + chart: {{ template "unctl.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + name: {{ template "unctl.fullname" . }} +spec: + {{- if .Values.service.loadbalancer }} + type: LoadBalancer + {{- end }} + selector: + app: {{ template "unctl.name" . }} + ports: + - protocol: TCP + port: {{ .Values.service.port }} + targetPort: {{ if .Values.frontend.enabled }}http{{ else }}api{{ end }} +{{- end}} diff --git a/packs/unctl-1.1.0/charts/unctl/templates/servieaccount.yaml b/packs/unctl-1.1.0/charts/unctl/templates/servieaccount.yaml new file mode 100644 index 00000000..d3503964 --- /dev/null +++ b/packs/unctl-1.1.0/charts/unctl/templates/servieaccount.yaml @@ -0,0 +1,11 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: {{ template "unctl.name" . }} + chart: {{ template "unctl.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + name: {{ template "unctl.serviceAccountName" . }} +{{- end -}} diff --git a/packs/unctl-1.1.0/charts/unctl/values.yaml b/packs/unctl-1.1.0/charts/unctl/values.yaml new file mode 100644 index 00000000..081a67c7 --- /dev/null +++ b/packs/unctl-1.1.0/charts/unctl/values.yaml @@ -0,0 +1,68 @@ +frontend: + # defines whether it should contains frontend application + enabled: true + +service: + # defines whether it should create service + enabled: true + # defines whether service should be a loadbalancer + loadbalancer: true + # port exposed in service + port: 8000 + +# By default checks will run at 12 AM every day +schedule: "0 0 * * *" + +# List of namespaces to conduct checks on +namespaces: [] + +# value in days to prevent disk space build up for embedded DB +# by deafult it will use 7 days +retention_period: 7 + +# Defaults to .Chart.Name +nameOverride: "" +# Defaults to .Release.Name-.Chart.Name +fullnameOverride: "" + +image: + registry: public.ecr.aws + api: unskript/unctl + frontend: unskript/unctl-frontend + tag: latest + pullPolicy: Always + +rbac: + # If true, create & use RBAC resources + create: true + +serviceAccount: + # Specifies whether a ServiceAccount should be created + create: true + # The name of the ServiceAccount to use. + # If not set and create is true, a name is generated using the fullname template + name: + +resources: {} +# limits: +# cpu: 100m +# memory: 300Mi +# requests: +# cpu: 100m +# memory: 300Mi + +# Affinity for pod assignment +# Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +# affinity: {} + +# Tolerations for pod assignment +# Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +tolerations: [] + +# Node labels for pod assignment +# Ref: https://kubernetes.io/docs/user-guide/node-selection/ +nodeSelector: {} + +podAnnotations: {} +podLabels: {} +replicaCount: 1 diff --git a/packs/unctl-1.1.0/logo.png b/packs/unctl-1.1.0/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fae62df7217fe8096aee09b189a38d618d074b73 GIT binary patch literal 121080 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 Date: Fri, 24 May 2024 12:54:27 -0400 Subject: [PATCH 16/22] Add oam-app-controller 0.0.3. Signed-off-by: Matt Welke --- packs/oam-app-controller-0.0.3/README.md | 14 + .../charts/app-core-0.0.3.tgz | Bin 0 -> 41559 bytes .../charts/flux2-2.12.4.tgz | Bin 0 -> 63679 bytes .../charts/zot-0.1.50.tgz | Bin 0 -> 6690 bytes packs/oam-app-controller-0.0.3/logo.png | Bin 0 -> 1757 bytes packs/oam-app-controller-0.0.3/pack.json | 19 + packs/oam-app-controller-0.0.3/schema.yaml | 2 + packs/oam-app-controller-0.0.3/values.yaml | 703 ++++++++++++++++++ 8 files changed, 738 insertions(+) create mode 100644 packs/oam-app-controller-0.0.3/README.md create mode 100644 packs/oam-app-controller-0.0.3/charts/app-core-0.0.3.tgz create mode 100644 packs/oam-app-controller-0.0.3/charts/flux2-2.12.4.tgz create mode 100644 packs/oam-app-controller-0.0.3/charts/zot-0.1.50.tgz create mode 100644 packs/oam-app-controller-0.0.3/logo.png create mode 100644 packs/oam-app-controller-0.0.3/pack.json create mode 100644 packs/oam-app-controller-0.0.3/schema.yaml create mode 100644 packs/oam-app-controller-0.0.3/values.yaml diff --git a/packs/oam-app-controller-0.0.3/README.md b/packs/oam-app-controller-0.0.3/README.md new file mode 100644 index 00000000..870ebe9d --- /dev/null +++ b/packs/oam-app-controller-0.0.3/README.md @@ -0,0 +1,14 @@ +# OAM App Controller + +## Overview +The OAM App Controller is a pack of packs used to deploy OAM applications. +The internal packs within the OAM App Controller are the app-core, flux2, and zot. + +## CloudTypes supported: +Supported for all cloudTypes + +## References: +* [Flux](https://fluxcd.io/) +* [Github Flux](https://github.com/fluxcd/flux2) +* [Zot](https://zotregistry.dev) +* [Github Zot](https://github.com/project-zot/zot) diff --git a/packs/oam-app-controller-0.0.3/charts/app-core-0.0.3.tgz b/packs/oam-app-controller-0.0.3/charts/app-core-0.0.3.tgz new file mode 100644 index 0000000000000000000000000000000000000000..c5ef732eb6d68416778b047bda0e6138309db4f1 GIT binary patch literal 41559 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/? + -> backend where where parts of the url correspond to + RFC 3986, this resource will be used to match against + everything after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map requests + to backends. + items: + description: HTTPIngressPath associates a path with + a backend. Incoming urls matching the path are forwarded + to the backend. + properties: + backend: + description: Backend defines the referenced service + endpoint to which the traffic will be forwarded + to. + properties: + resource: + description: Resource is an ObjectRef to another + Kubernetes resource in the namespace of + the Ingress object. If resource is specified, + a service.Name and service.Port must not + be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If APIGroup + is not specified, the specified Kind + must be in the core API group. For any + other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + service: + description: Service references a Service + as a Backend. This is a mutually exclusive + setting with "Resource". + properties: + name: + description: Name is the referenced service. + The service must exist in the same namespace + as the Ingress object. + type: string + port: + description: Port of the referenced service. + A port name or port number is required + for a IngressServiceBackend. + properties: + name: + description: Name is the name of the + port on the Service. This is a mutually + exclusive setting with "Number". + type: string + number: + description: Number is the numerical + port number (e.g. 80) on the Service. + This is a mutually exclusive setting + with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the path + of an incoming request. Currently it can contain + characters disallowed from the conventional + "path" part of a URL as defined by RFC 3986. + Paths must begin with a '/' and must be present + when using PathType with value "Exact" or "Prefix". + type: string + pathType: + description: 'PathType determines the interpretation + of the Path matching. PathType can be one of + the following values: * Exact: Matches the URL + path exactly. * Prefix: Matches based on a URL + path prefix split by ''/''. Matching is done + on a path element by element basis. A path element + refers is the list of labels in the path split + by the ''/'' separator. A request is a match + for path p if every p is an element-wise prefix + of p of the request path. Note that if the last + element of the path is a substring of the last + element in request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does not + match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching is up to + the IngressClass. Implementations can treat + this as a separate PathType or treat it identically + to Prefix or Exact path types. Implementations + are required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + required: + - http + type: object + type: array + tls: + description: TLS configuration. Currently the Ingress only supports + a single TLS port, 443. If multiple members of this list specify + different hosts, they will be multiplexed on the same port according + to the hostname specified through the SNI TLS extension, if + the ingress controller fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer security + associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included in the TLS + certificate. The values in this list must match the name/s + used in the tlsSecret. Defaults to the wildcard host setting + for the loadbalancer controller fulfilling this Ingress, + if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret used to + terminate TLS traffic on port 443. Field is left optional + to allow TLS routing based on SNI hostname alone. If the + SNI host in a listener conflicts with the "Host" header + field used by an IngressRule, the SNI host is used for + termination and value of the Host header is used for routing. + type: string + type: object + type: array + type: object + strategy: + description: Gslb Strategy spec + properties: + dnsTtlSeconds: + description: Defines DNS record TTL in seconds + type: integer + primaryGeoTag: + description: Primary Geo Tag. Valid for failover strategy only + type: string + splitBrainThresholdSeconds: + description: Split brain TXT record expiration in seconds + type: integer + type: + description: Load balancing strategy type:(roundRobin|failover) + type: string + weight: + additionalProperties: + type: integer + description: Weight is defined by map region:weight + type: object + required: + - type + type: object + required: + - ingress + - strategy + type: object + status: + description: GslbStatus defines the observed state of Gslb + properties: + geoTag: + description: Cluster Geo Tag + type: string + healthyRecords: + additionalProperties: + items: + type: string + type: array + description: Current Healthy DNS record structure + type: object + hosts: + description: Comma-separated list of hosts. Duplicating the value + from range .spec.ingress.rules[*].host for printer column + type: string + serviceHealth: + additionalProperties: + type: string + description: Associated Service status + type: object + required: + - geoTag + - healthyRecords + - serviceHealth + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/NOTES.txt b/packs/k8gb-0.12.2/charts/k8gb/templates/NOTES.txt new file mode 100644 index 00000000..3a529a09 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/NOTES.txt @@ -0,0 +1,25 @@ +done + _ ___ _ + | | _( _ ) __ _| |__ + | |/ / _ \ / _` | '_ \ + | < (_) | (_| | |_) | + |_|\_\___/ \__, |_.__/ & all dependencies are installed + |___/ + +{{- if and .Values.tracing.enabled .Values.tracing.deployJaeger }} + + +To check the OpenTelemetry (tracing) data: +------------------------------------------ +kubectl port-forward svc/jaeger-collector -n k8gb 16686 +open http://localhost:16686 + +{{- end }} + +1. Check if your DNS Zone is served by K8GB CoreDNS + $ kubectl -n {{ .Release.Namespace }} run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools --command -- /usr/bin/dig @{{ .Release.Name }}-coredns SOA . +short + +If everything is fine then you are expected to see similar output: +``` +ns1.dns. hostmaster.dns. 1616173200 7200 1800 86400 3600 +``` diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/_helpers.tpl b/packs/k8gb-0.12.2/charts/k8gb/templates/_helpers.tpl new file mode 100644 index 00000000..ecca6b19 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/_helpers.tpl @@ -0,0 +1,154 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "chart.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "chart.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chart.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "chart.labels" -}} +helm.sh/chart: {{ include "chart.chart" . }} +{{ include "chart.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "chart.selectorLabels" -}} +app.kubernetes.io/name: {{ include "chart.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "chart.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "chart.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{- define "k8gb.extdnsProvider" -}} +{{- if .Values.ns1.enabled -}} +{{- print "ns1" -}} +{{- end -}} +{{- if .Values.route53.enabled }} +{{- print "aws" -}} +{{- end -}} +{{- if .Values.rfc2136.enabled }} +{{- print "rfc2136" -}} +{{- end -}} +{{- if .Values.cloudflare.enabled }} +{{- print "cloudflare" -}} +{{- end -}} +{{- end -}} + +{{- define "k8gb.extdnsOwnerID" -}} +{{- if .Values.route53.enabled -}} +k8gb-{{ .Values.route53.hostedZoneID }}-{{ .Values.k8gb.clusterGeoTag }} +{{- else -}} +k8gb-{{ .Values.k8gb.dnsZone }}-{{ .Values.k8gb.clusterGeoTag }} +{{- end -}} +{{- end -}} + +{{- define "k8gb.edgeDNSServers" -}} +{{ join "," .Values.k8gb.edgeDNSServers }} +{{- end -}} + +{{- define "k8gb.extdnsProviderOpts" -}} +{{- if .Values.ns1.enabled -}} +{{- if .Values.ns1.endpoint -}} + - --ns1-endpoint={{ .Values.ns1.endpoint }} +{{- end -}} +{{- if .Values.ns1.ignoreSSL -}} + - --ns1-ignoressl +{{- end -}} + env: + - name: NS1_APIKEY + valueFrom: + secretKeyRef: + name: ns1 + key: apiKey +{{- end }} +{{- if and (eq .Values.rfc2136.enabled true) (eq .Values.rfc2136.rfc2136auth.insecure.enabled true) -}} + - --rfc2136-insecure +{{- end -}} +{{- if and (eq .Values.rfc2136.enabled true) (eq .Values.rfc2136.rfc2136auth.tsig.enabled true) -}} + - --rfc2136-tsig-axfr +{{- range $k, $v := .Values.rfc2136.rfc2136auth.tsig.tsigCreds -}} +{{- range $kk, $vv := $v }} + - --rfc2136-{{ $kk }}={{ $vv }} +{{- end }} +{{- end }} +{{- end -}} +{{- if and (eq .Values.rfc2136.enabled true) (eq .Values.rfc2136.rfc2136auth.gssTsig.enabled true) -}} + - --rfc2136-gss-tsig +{{- range $k, $v := .Values.rfc2136.rfc2136auth.gssTsig.gssTsigCreds -}} +{{- range $kk, $vv := $v }} + - --rfc2136-{{ $kk }}={{ $vv }} +{{- end }} +{{- end }} +{{- end -}} +{{ if .Values.rfc2136.enabled -}} +{{- range $k, $v := .Values.rfc2136.rfc2136Opts -}} +{{- range $kk, $vv := $v }} + - --rfc2136-{{ $kk }}={{ $vv }} +{{- end }} +{{- end }} + - --rfc2136-zone={{ .Values.k8gb.edgeDNSZone }} + env: + - name: EXTERNAL_DNS_RFC2136_TSIG_SECRET + valueFrom: + secretKeyRef: + name: rfc2136 + key: secret +{{- end -}} +{{- if .Values.cloudflare.enabled -}} + - --zone-id-filter={{ .Values.cloudflare.zoneID }} + - --cloudflare-dns-records-per-page={{ + .Values.cloudflare.dnsRecordsPerPage | default 5000 }} + env: + - name: CF_API_TOKEN + valueFrom: + secretKeyRef: + name: cloudflare + key: token +{{- end -}} +{{- end -}} +{{- define "k8gb.metrics_port" -}} +{{ print (split ":" .Values.k8gb.metricsAddress)._1 }} +{{- end -}} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/coredns-cm.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/coredns-cm.yaml new file mode 100644 index 00000000..9fd6d740 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/coredns-cm.yaml @@ -0,0 +1,25 @@ +{{- if .Values.coredns.deployment.enabled }} +kind: ConfigMap +metadata: + labels: +{{ include "chart.labels" . | indent 4 }} + name: {{ .Release.Name }}-coredns +apiVersion: v1 +data: + Corefile: |- + {{ .Values.k8gb.dnsZone }}:5353 { + errors + health +{{- if .Values.k8gb.coredns.extra_plugins }} +{{ .Values.k8gb.coredns.extra_plugins | indent 8}} +{{- end }} + ready + prometheus 0.0.0.0:9153 + forward . /etc/resolv.conf + k8s_crd { + filter k8gb.absa.oss/dnstype=local + negttl {{ .Values.k8gb.dnsZoneNegTTL }} + loadbalance weight + } + } +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/coredns/rbac.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/coredns/rbac.yaml new file mode 100644 index 00000000..1b02f8b0 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/coredns/rbac.yaml @@ -0,0 +1,35 @@ +{{- if and .Values.coredns.deployment.enabled .Values.coredns.rbac.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: coredns-cluster-role +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - list + - watch +- apiGroups: + - externaldns.k8s.io + resources: + - dnsendpoints + verbs: + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: coredns-clusterrole-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: coredns-cluster-role +subjects: +- kind: ServiceAccount + name: coredns + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/crds-template.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/crds-template.yaml new file mode 100644 index 00000000..8c050c13 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/crds-template.yaml @@ -0,0 +1,9 @@ +{{- if .Values.k8gb.deployCrds }} + +{{- $files := .Files }} +{{- range tuple "crd/k8gb.absa.oss_gslbs.yaml" "crd/dns-endpoint-crd-manifest.yaml" }} +{{ $files.Get . }} + +{{- end }} + +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/deployment.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/deployment.yaml new file mode 100644 index 00000000..f1583797 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/deployment.yaml @@ -0,0 +1,147 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: k8gb + namespace: {{ .Release.Namespace }} + labels: +{{ include "chart.labels" . | indent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + name: k8gb + template: + metadata: + labels: + name: k8gb + annotations: + kubectl.kubernetes.io/default-container: k8gb + spec: + serviceAccountName: k8gb + containers: + - name: k8gb + ports: + - containerPort: {{ include "k8gb.metrics_port" . }} + name: metrics + image: {{ .Values.k8gb.imageRepo }}:{{ .Values.k8gb.imageTag | default .Chart.AppVersion }} + imagePullPolicy: IfNotPresent + {{- if .Values.k8gb.securityContext }} + securityContext: + {{- toYaml .Values.k8gb.securityContext | nindent 12 }} + {{- end }} + resources: + requests: + memory: "32Mi" + cpu: "100m" + limits: + memory: "128Mi" + cpu: "500m" + env: + - name: WATCH_NAMESPACE + value: "" + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: OPERATOR_NAME + value: "k8gb" + - name: CLUSTER_GEO_TAG + value: {{ quote .Values.k8gb.clusterGeoTag }} + - name: EXT_GSLB_CLUSTERS_GEO_TAGS + value: {{ quote .Values.k8gb.extGslbClustersGeoTags }} + - name: EDGE_DNS_ZONE + value: {{ .Values.k8gb.edgeDNSZone }} + - name: EDGE_DNS_SERVERS + value: {{ include "k8gb.edgeDNSServers" . }} + - name: DNS_ZONE + value: {{ .Values.k8gb.dnsZone }} + - name: RECONCILE_REQUEUE_SECONDS + value: {{ quote .Values.k8gb.reconcileRequeueSeconds}} + {{- if .Values.infoblox.enabled }} + - name: INFOBLOX_GRID_HOST + valueFrom: + configMapKeyRef: + name: infoblox + key: INFOBLOX_GRID_HOST + - name: INFOBLOX_WAPI_VERSION + valueFrom: + configMapKeyRef: + name: infoblox + key: INFOBLOX_WAPI_VERSION + - name: INFOBLOX_WAPI_PORT + valueFrom: + configMapKeyRef: + name: infoblox + key: INFOBLOX_WAPI_PORT + - name: INFOBLOX_HTTP_REQUEST_TIMEOUT + valueFrom: + configMapKeyRef: + name: infoblox + key: INFOBLOX_HTTP_REQUEST_TIMEOUT + - name: INFOBLOX_HTTP_POOL_CONNECTIONS + valueFrom: + configMapKeyRef: + name: infoblox + key: INFOBLOX_HTTP_POOL_CONNECTIONS + - name: INFOBLOX_WAPI_USERNAME + valueFrom: + secretKeyRef: + name: infoblox + key: INFOBLOX_WAPI_USERNAME + - name: INFOBLOX_WAPI_PASSWORD + valueFrom: + secretKeyRef: + name: infoblox + key: INFOBLOX_WAPI_PASSWORD + {{- end }} + {{- if or .Values.route53.enabled .Values.ns1.enabled .Values.rfc2136.enabled .Values.cloudflare.enabled }} + - name: EXTDNS_ENABLED + value: "true" + {{- end }} + {{- if eq "LoadBalancer" ( toString .Values.coredns.serviceType ) }} + - name: COREDNS_EXPOSED + value: "true" + {{- end }} + {{- if .Values.tracing.enabled }} + {{- with .Values.tracing }} + - name: TRACING_ENABLED + value: {{ .enabled | quote }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .endpoint | quote }} + {{- with .samplingRatio }} + - name: TRACING_SAMPLING_RATIO + value: {{ . | quote }} + {{- end }} + {{- end }} + {{- end }} + - name: LOG_FORMAT + value: {{ quote .Values.k8gb.log.format }} + - name: LOG_LEVEL + value: {{ quote .Values.k8gb.log.level }} + - name: NO_COLOR + value: "true" + - name: SPLIT_BRAIN_CHECK + value: {{ quote .Values.k8gb.splitBrainCheck }} + - name: METRICS_ADDRESS + value: {{ .Values.k8gb.metricsAddress }} + {{- if .Values.tracing.enabled }} + - image: {{ .Values.tracing.sidecarImage.repository }}:{{ .Values.tracing.sidecarImage.tag }} + name: otel-collector + imagePullPolicy: {{ .Values.tracing.sidecarImage.pullPolicy }} + args: + - --config=/conf/agent.yaml + volumeMounts: + - mountPath: /conf + name: agent-config + volumes: + - configMap: + items: + - key: agent.yaml + path: agent.yaml + name: agent-config + name: agent-config + {{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/external-dns/external-dns.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/external-dns/external-dns.yaml new file mode 100644 index 00000000..a8ce5707 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/external-dns/external-dns.yaml @@ -0,0 +1,74 @@ +{{- if or .Values.ns1.enabled .Values.route53.enabled .Values.rfc2136.enabled .Values.cloudflare.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns +spec: + strategy: + type: Recreate + selector: + matchLabels: + app: external-dns + template: + metadata: + labels: + app: external-dns + spec: + serviceAccountName: k8gb-external-dns + securityContext: +{{ toYaml .Values.externaldns.securityContext | indent 8 }} + containers: + - name: external-dns + image: {{ .Values.externaldns.image }} + args: + - --source=crd + - --domain-filter={{ .Values.k8gb.edgeDNSZone }} # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones + - --policy=sync # enable full synchronization including record removal + - --log-level=debug # debug only + - --managed-record-types=A + - --managed-record-types=CNAME + - --managed-record-types=NS + - --annotation-filter=k8gb.absa.oss/dnstype=extdns # filter out only relevant DNSEntrypoints + - --txt-owner-id={{ include "k8gb.extdnsOwnerID" . }} + - --txt-prefix=k8gb-{{ .Values.k8gb.clusterGeoTag }}- # add custom prefix to TXT records, critical for Cloudflare NS record creation + - --provider={{ include "k8gb.extdnsProvider" . }} + {{- if and .Values.route53.assumeRoleArn (not .Values.route53.secret) }} + - --aws-assume-role={{ .Values.route53.assumeRoleArn }} + {{- end }} + {{ include "k8gb.extdnsProviderOpts" . }} + resources: + requests: + memory: "32Mi" + cpu: "100m" + limits: + memory: "128Mi" + cpu: "500m" + securityContext: + readOnlyRootFilesystem: true + {{- if .Values.route53.secret }} + env: + - name: AWS_SHARED_CREDENTIALS_FILE + value: /.aws/credentials + volumeMounts: + - name: aws-credentials + mountPath: /.aws + readOnly: true + volumes: + - name: aws-credentials + secret: + secretName: {{ .Values.route53.secret }} + {{- end }} + {{- if .Values.rfc2136.rfc2136auth.gssTsig.enabled }} + volumeMounts: + - mountPath: /etc/krb5.conf + name: kerberos-config-volume + subPath: krb5.conf + dnsPolicy: {{ .Values.externaldns.dnsPolicy }} + volumes: + - name: kerberos-config-volume + configMap: + name: {{ .Values.rfc2136.rfc2136auth.gssTsig.kerberosConfigmap }} + defaultMode: 420 + {{- end }} + +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/external-dns/rbac.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/external-dns/rbac.yaml new file mode 100644 index 00000000..8cc12041 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/external-dns/rbac.yaml @@ -0,0 +1,37 @@ +{{- if or .Values.ns1.enabled .Values.route53.enabled .Values.rfc2136.enabled .Values.cloudflare.enabled }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: k8gb-external-dns +rules: +- apiGroups: ["externaldns.k8s.io"] + resources: ["dnsendpoints"] + verbs: ["get","watch","list"] +- apiGroups: ["externaldns.k8s.io"] + resources: ["dnsendpoints/status"] + verbs: ["*"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: k8gb-external-dns-viewer +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: k8gb-external-dns +subjects: +- kind: ServiceAccount + name: k8gb-external-dns + namespace: {{ .Release.Namespace }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: k8gb-external-dns + namespace: {{ .Release.Namespace }} +{{- if and .Values.route53.enabled .Values.route53.irsaRole }} + annotations: + eks.amazonaws.com/role-arn: {{ .Values.route53.irsaRole }} +{{- end }} +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/infoblox-cm.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/infoblox-cm.yaml new file mode 100644 index 00000000..4627d0c5 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/infoblox-cm.yaml @@ -0,0 +1,14 @@ +{{- if .Values.infoblox.enabled }} +apiVersion: v1 +data: + INFOBLOX_GRID_HOST: {{ quote .Values.infoblox.gridHost }} + INFOBLOX_WAPI_VERSION: {{ quote .Values.infoblox.wapiVersion }} + INFOBLOX_WAPI_PORT: {{ quote .Values.infoblox.wapiPort }} + INFOBLOX_HTTP_REQUEST_TIMEOUT: {{ quote .Values.infoblox.httpRequestTimeout }} + INFOBLOX_HTTP_POOL_CONNECTIONS: {{ quote .Values.infoblox.httpPoolConnections }} +kind: ConfigMap +metadata: + name: infoblox + labels: +{{ include "chart.labels" . | indent 4 }} +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/metrics-service.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/metrics-service.yaml new file mode 100644 index 00000000..c73ab92c --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/metrics-service.yaml @@ -0,0 +1,16 @@ +{{- if or .Values.k8gb.exposeMetrics .Values.k8gb.serviceMonitor.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: k8gb-metrics + labels: + {{- include "chart.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: {{ include "k8gb.metrics_port" . }} + protocol: TCP + name: metrics + selector: + {{- include "chart.selectorLabels" . | nindent 4 }} +{{- end -}} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/otel/jaeger-deployment.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/otel/jaeger-deployment.yaml new file mode 100644 index 00000000..2a951e28 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/otel/jaeger-deployment.yaml @@ -0,0 +1,39 @@ +{{- if .Values.tracing.enabled }} +{{- if .Values.tracing.deployJaeger }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: jaeger + labels: +{{ include "chart.labels" . | indent 4 }} +spec: + selector: + matchLabels: + id: jaeger + replicas: 1 + template: + metadata: + labels: + id: jaeger + spec: + containers: + - name: jaeger + image: {{ .Values.tracing.jaegerImage.repository }}:{{ .Values.tracing.jaegerImage.tag }} + imagePullPolicy: {{ .Values.tracing.jaegerImage.pullPolicy }} + readinessProbe: + httpGet: + path: "/" + port: 14269 + initialDelaySeconds: 5 + env: + - name: COLLECTOR_OTLP_ENABLED + value: "true" + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi +{{- end }} +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/otel/jaeger-svc.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/otel/jaeger-svc.yaml new file mode 100644 index 00000000..1874439f --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/otel/jaeger-svc.yaml @@ -0,0 +1,27 @@ +{{- if .Values.tracing.enabled }} +{{- if .Values.tracing.deployJaeger }} +apiVersion: v1 +kind: Service +metadata: + name: jaeger-collector + labels: +{{ include "chart.labels" . | indent 4 }} +spec: + ports: + - name: dashboard + port: 16686 + protocol: TCP + targetPort: 16686 + - name: grpc-otlp-collector + port: 4317 + protocol: TCP + targetPort: 4317 + - name: http-otlp-collector + port: 4318 + protocol: TCP + targetPort: 4318 + selector: + id: jaeger + type: ClusterIP +{{- end }} +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/otel/otel-config.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/otel/otel-config.yaml new file mode 100644 index 00000000..8db88ba9 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/otel/otel-config.yaml @@ -0,0 +1,36 @@ +{{- if .Values.tracing.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: agent-config + namespace: k8gb + labels: +{{ include "chart.labels" . | indent 4 }} +data: +{{- if or .Values.tracing.deployJaeger (not .Values.tracing.otelConfig ) }} + agent.yaml: | + receivers: + otlp: + protocols: + http: + grpc: + processors: + exporters: + otlp: + endpoint: jaeger-collector.k8gb:4317 + tls: + insecure: true + retry_on_failure: + enabled: true + logging: + service: + pipelines: + traces: + receivers: [otlp] + processors: [] + exporters: [otlp] +{{- else -}} + agent.yaml: | +{{ toYaml .Values.tracing.otelConfig | indent 4 }} +{{- end }} +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/otel/otel-svc.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/otel/otel-svc.yaml new file mode 100644 index 00000000..0d141489 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/otel/otel-svc.yaml @@ -0,0 +1,21 @@ +{{- if .Values.tracing.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: otel-collector + labels: +{{ include "chart.labels" . | indent 4 }} +spec: + ports: + - name: http-otlp + port: 4318 + protocol: TCP + targetPort: 4318 + - name: grpc-otlp + port: 4317 + protocol: TCP + targetPort: 4317 + selector: + name: k8gb + type: ClusterIP +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/role.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/role.yaml new file mode 100644 index 00000000..15502a90 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/role.yaml @@ -0,0 +1,59 @@ +{{- if .Values.k8gb.deployRbac }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: k8gb + labels: +{{ include "chart.labels" . | indent 4 }} +rules: +- apiGroups: + - "" + resources: + - endpoints + - services + verbs: + - 'get' + - 'list' + - 'watch' +- apiGroups: + - k8gb.absa.oss + resources: + - '*' + - gslbs + verbs: + - '*' +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - '*' +- apiGroups: + - externaldns.k8s.io + resources: + - dnsendpoints + verbs: + - '*' +- apiGroups: + - "" + resources: + - namespaces + verbs: + - 'list' +{{- if .Values.openshift.enabled }} +- apiGroups: + - route.openshift.io + resources: + - routes/custom-host + verbs: + - create + - update +- apiGroups: + - networking.k8s.io + resources: + - ingresses/finalizers + verbs: + - update +{{- end }} +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/role_binding.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/role_binding.yaml new file mode 100644 index 00000000..3b37994f --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/role_binding.yaml @@ -0,0 +1,16 @@ +{{- if .Values.k8gb.deployRbac }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: k8gb + labels: +{{ include "chart.labels" . | indent 4 }} +subjects: +- kind: ServiceAccount + name: k8gb + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: k8gb + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/service_account.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/service_account.yaml new file mode 100644 index 00000000..d54b17e8 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/service_account.yaml @@ -0,0 +1,10 @@ +{{- if .Values.k8gb.deployRbac }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: k8gb + namespace: {{ .Release.Namespace }} + labels: +{{ include "chart.labels" . | indent 4 }} +imagePullSecrets: {{ toYaml .Values.global.imagePullSecrets | nindent 2 }} +{{- end }} diff --git a/packs/k8gb-0.12.2/charts/k8gb/templates/servicemonitor.yaml b/packs/k8gb-0.12.2/charts/k8gb/templates/servicemonitor.yaml new file mode 100644 index 00000000..3f5ed2dd --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/templates/servicemonitor.yaml @@ -0,0 +1,14 @@ +{{- if .Values.k8gb.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: k8gb + labels: + {{- include "chart.labels" . | nindent 4 }} +spec: + endpoints: + - port: metrics + selector: + matchLabels: + {{- include "chart.selectorLabels" . | nindent 6 }} +{{- end -}} diff --git a/packs/k8gb-0.12.2/charts/k8gb/values.schema.json b/packs/k8gb-0.12.2/charts/k8gb/values.schema.json new file mode 100644 index 00000000..be8f49e6 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/values.schema.json @@ -0,0 +1,663 @@ +{ + "title": "values.yaml for k8gb helm chart", + "$ref": "#/definitions/All", + "definitions": { + "All": { + "type": "object", + "additionalProperties": false, + "properties": { + "global": { + "$ref": "#/definitions/Global" + }, + "k8gb": { + "$ref": "#/definitions/k8gb" + }, + "externaldns": { + "$ref": "#/definitions/Externaldns" + }, + "coredns": { + "$ref": "#/definitions/Coredns" + }, + "infoblox": { + "$ref": "#/definitions/Infoblox" + }, + "route53": { + "$ref": "#/definitions/Route53" + }, + "ns1": { + "$ref": "#/definitions/Ns1" + }, + "rfc2136": { + "$ref": "#/definitions/Rfc2136" + }, + "cloudflare": { + "$ref": "#/definitions/Cloudflare" + }, + "openshift": { + "$ref": "#/definitions/Openshift" + }, + "tracing": { + "$ref": "#/definitions/Tracing" + } + } + }, + "Coredns": { + "type": "object", + "additionalProperties": true, + "properties": { + "isClusterService": { + "type": "boolean" + }, + "deployment": { + "$ref": "#/definitions/CorednsDeployment" + }, + "image": { + "$ref": "#/definitions/CorednsImage" + }, + "serviceAccount": { + "$ref": "#/definitions/CorednsServiceAccount" + } + }, + "title": "Coredns" + }, + "CorednsDeployment": { + "type": "object", + "additionalProperties": true, + "properties": { + "skipConfig": { + "type": "boolean" + } + }, + "title": "Deployment" + }, + "CorednsImage": { + "type": "object", + "additionalProperties": true, + "properties": { + "repository": { + "type": "string", + "minLength": 1 + }, + "tag": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "repository", + "tag" + ], + "title": "Image" + }, + "CorednsServiceAccount": { + "type": "object", + "additionalProperties": true, + "properties": { + "create": { + "type": "boolean" + }, + "name": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "name" + ], + "title": "ServiceAccount" + }, + "Externaldns": { + "type": "object", + "additionalProperties": false, + "properties": { + "dnsPolicy": { + "type": "string", + "minLength": 1 + }, + "image": { + "type": "string", + "minLength": 1 + }, + "interval": { + "type": "string" + }, + "securityContext": { + "$ref": "#/definitions/ExternaldnsSecurityContext" + } + }, + "title": "Externaldns" + }, + "ExternaldnsSecurityContext": { + "type": "object", + "additionalProperties": false, + "properties": { + "runAsUser": { + "type": "integer", + "minimum": 0 + }, + "fsGroup": { + "type": "integer", + "minimum": 0 + }, + "runAsNonRoot": { + "type": "boolean" + } + }, + "title": "ExternaldnsSecurityContext" + }, + "Global": { + "type": "object", + "additionalProperties": false, + "properties": { + "fleet": { + "type": "object" + }, + "imagePullSecrets": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "description": "Name of secret" + } + } + }, + "description": "ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet. More info: http://kubernetes.io/docs/user-guide/secrets#manually-specifying-an-imagepullsecret" + } + }, + "title": "Global" + }, + "Image": { + "type": "object", + "additionalProperties": false, + "properties": { + "repository": { + "type": "string", + "minLength": 1 + }, + "pullPolicy": { + "enum": [ + "Always", + "IfNotPresent", + "Never" + ] + }, + "tag": { + "type": "string" + } + } + }, + "Infoblox": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "gridHost": { + "format": "idn-hostname" + }, + "wapiVersion": { + "type": "string", + "minLength": 1 + }, + "wapiPort": { + "type": "integer", + "minimum": 1, + "maximum": 65535 + }, + "sslVerify": { + "type": "boolean" + }, + "httpRequestTimeout": { + "type": "integer", + "minimum": 0 + }, + "httpPoolConnections": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "gridHost", + "wapiPort" + ], + "title": "Infoblox" + }, + "k8gb": { + "type": "object", + "additionalProperties": false, + "properties": { + "imageRepo": { + "type": "string", + "minLength": 1 + }, + "imageTag": { + "type": [ + "string", + "null" + ] + }, + "deployCrds": { + "type": "boolean" + }, + "deployRbac": { + "type": "boolean" + }, + "dnsZone": { + "format": "idn-hostname", + "minLength": 1 + }, + "dnsZoneNegTTL": { + "type": "integer", + "minimum": 0 + }, + "edgeDNSZone": { + "format": "idn-hostname", + "minLength": 1 + }, + "edgeDNSServers": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + } + }, + "clusterGeoTag": { + "type": "string", + "minLength": 1 + }, + "extGslbClustersGeoTags": { + "type": "string", + "minLength": 1 + }, + "reconcileRequeueSeconds": { + "type": "integer", + "minimum": 0 + }, + "log": { + "$ref": "#/definitions/k8gbLog" + }, + "coredns": { + "$ref": "#/definitions/k8gbCoreDNS" + }, + "splitBrainCheck": { + "type": "boolean" + }, + "metricsAddress": { + "type": "string", + "minLength": 1 + }, + "securityContext": { + "$ref": "#/definitions/k8gbSecurityContext" + }, + "exposeMetrics": { + "type": "boolean", + "default": false + }, + "serviceMonitor": { + "$ref": "#/definitions/k8gbServiceMonitor" + } + }, + "required": [ + "clusterGeoTag", + "extGslbClustersGeoTags", + "dnsZone", + "edgeDNSServers", + "edgeDNSZone" + ], + "title": "k8gb" + }, + "k8gbLog": { + "type": "object", + "additionalProperties": false, + "properties": { + "format": { + "enum": [ + "simple", + "json" + ] + }, + "level": { + "enum": [ + "panic", + "fatal", + "error", + "warn", + "info", + "debug", + "trace" + ] + } + }, + "title": "Log" + }, + "k8gbCoreDNS": { + "type": "object", + "additionalProperties": false, + "properties": { + "extra_plugins": { + "type": "string" + } + }, + "title": "k8gbCoredns" + }, + "k8gbSecurityContext": { + "type": "object", + "additionalProperties": false, + "properties": { + "runAsNonRoot": { + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer", + "minimum": 0 + } + }, + "title": "k8gbSecurityContext" + }, + "k8gbServiceMonitor": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "Ns1": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "ignoreSSL": { + "type": "boolean" + } + }, + "title": "Ns1" + }, + "Openshift": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + } + }, + "title": "Openshift" + }, + "Rfc2136": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "rfc2136Opts": { + "type": "array", + "items": { + "$ref": "#/definitions/Rfc2136Opt" + } + }, + "rfc2136auth": { + "type": "object", + "items": { + "$ref": "#/definitions/Rfc2136auth" + } + } + }, + "required": [ + "rfc2136Opts" + ], + "title": "Rfc2136" + }, + "Rfc2136Opt": { + "type": "object", + "additionalProperties": false, + "properties": { + "host": { + "format": "idn-hostname" + }, + "port": { + "type": "integer", + "minimum": 1, + "maximum": 65535 + } + }, + "title": "Rfc2136Opt" + }, + "Rfc2136auth": { + "type": "object", + "additionalProperties": false, + "properties": { + "insecure": { + "type": "object", + "items": { + "$ref": "#/definitions/Rfc2136authInsecure" + } + }, + "tsig": { + "type": "object", + "items": { + "$ref": "#/definitions/Rfc2136authTsig" + } + }, + "gssTsig": { + "type": "object", + "items": { + "$ref": "#/definitions/Rfc2136authGssTsig" + } + } + }, + "title": "Rfc2136auth" + }, + "Rfc2136authInsecure": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + } + }, + "title": "Rfc2136authInsecure" + }, + "Rfc2136authTsig": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean", + "default": true + }, + "tsigCreds": { + "type": "array", + "items": { + "$ref": "#/definitions/Rfc2136authTsigCreds" + } + } + }, + "title": "Rfc2136authTsig" + }, + "Rfc2136authTsigCreds": { + "type": "object", + "additionalProperties": false, + "properties": { + "tsig-secret-alg": { + "type": "string", + "minLength": 1 + }, + "tsig-keyname": { + "type": "string", + "minLength": 1 + } + }, + "title": "Rfc2136authTsigCreds" + }, + "Rfc2136authGssTsig": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "kerberosConfigMap": { + "type": "string", + "minLength": 1 + }, + "gssTsigCreds": { + "type": "array", + "items": { + "$ref": "#/definitions/Rfc2136authGssTsigCreds" + } + } + }, + "title": "Rfc2136authGssTsig" + }, + "Rfc2136authGssTsigCreds": { + "type": "object", + "additionalProperties": false, + "properties": { + "kerberos-username": { + "type": "string", + "minLength": 1 + }, + "kerberos-password": { + "type": "string", + "minLength": 1 + }, + "kerberos-realm": { + "type": "string", + "minLength": 1 + } + }, + "title": "Rfc2136authGssTsigCreds" + }, + "Route53": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "hostedZoneID": { + "type": "string", + "minLength": 2 + }, + "irsaRole": { + "oneOf": [ + { + "type": "string", + "pattern": "^arn:aws:iam:.+$", + "minLength": 20 + }, + { + "type": "null" + } + ] + }, + "secret": { + "oneOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "null" + } + ] + }, + "assumeRoleArn": { + "oneOf": [ + { + "type": "string", + "pattern": "^arn:aws:iam:.+$", + "minLength": 20 + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "hostedZoneID" + ], + "title": "Route53" + }, + "Cloudflare": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "dnsRecordsPerPage": { + "type": "integer" + }, + "zoneID": { + "type": "string" + } + }, + "required": [ + "enabled", + "zoneID" + ], + "title": "Cloudflare" + }, + "Tracing": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "deployJaeger": { + "type": "boolean" + }, + "endpoint": { + "type": "string", + "pattern": "^.{2,256}:\\d{2,5}$" + }, + "samplingRatio": { + "type": [ + "string", + "null" + ], + "pattern": "^(0(\\.\\d{1,3})?|1(\\.0)?)$" + }, + "otelConfig": { + "type": [ + "object", + "null" + ], + "additionalProperties": true + }, + "sidecarImage": { + "$ref": "#/definitions/Image" + }, + "jaegerImage": { + "$ref": "#/definitions/Image" + } + }, + "required": [ + "enabled" + ], + "title": "Tracing" + } + } +} diff --git a/packs/k8gb-0.12.2/charts/k8gb/values.yaml b/packs/k8gb-0.12.2/charts/k8gb/values.yaml new file mode 100644 index 00000000..86376604 --- /dev/null +++ b/packs/k8gb-0.12.2/charts/k8gb/values.yaml @@ -0,0 +1,197 @@ +global: + # -- Reference to one or more secrets to be used when pulling images + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + imagePullSecrets: [] + # - name: "image-pull-secret" + +k8gb: + # -- image repository + imageRepo: "docker.io/absaoss/k8gb" + # -- ( string ) image tag defaults to Chart.AppVersion, see Chart.yaml, but can be overrided with imageTag key + imageTag: + # -- whether it should also deploy the gslb and dnsendpoints CRDs + deployCrds: true + # -- whether it should also deploy the service account, cluster role and cluster role binding + deployRbac: true + # -- dnsZone controlled by gslb + dnsZone: "cloud.example.com" + # -- Negative TTL for SOA record + dnsZoneNegTTL: 300 + # -- main zone which would contain gslb zone to delegate + edgeDNSZone: "example.com" # main zone which would contain gslb zone to delegate + # -- host/ip[:port] format is supported here where port defaults to 53 + edgeDNSServers: + # -- use this DNS server as a main resolver to enable cross k8gb DNS based communication + - "1.1.1.1" + # -- used for places where we need to distinguish between different Gslb instances + clusterGeoTag: "eu" + # -- comma-separated list of external gslb geo tags to pair with + extGslbClustersGeoTags: "us" + # -- Reconcile time in seconds + reconcileRequeueSeconds: 30 + # -- Extra CoreDNS plugins to be enabled (yaml object) + coredns: + extra_plugins: "" + log: + # -- log format (simple,json) + format: simple # log format (simple,json) + # -- log level (panic,fatal,error,warn,info,debug,trace) + level: info # log level (panic,fatal,error,warn,info,debug,trace) + # -- Enable SplitBrain check (Infoblox only) + splitBrainCheck: false + # -- Metrics server address + metricsAddress: "0.0.0.0:8080" + securityContext: + # -- For more options consult https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#securitycontext-v1-core + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + runAsUser: 1000 + # -- Exposing metrics + exposeMetrics: false + # -- enable ServiceMonitor + serviceMonitor: + enabled: false + +externaldns: + # -- `.spec.template.spec.dnsPolicy` for ExternalDNS deployment + dnsPolicy: "ClusterFirst" + # -- external-dns image repo:tag + # It is important to use the image from k8gb external-dns fork to get the full + # functionality. See links below + # https://github.com/k8gb-io/external-dns + # https://github.com/k8gb-io/external-dns/pkgs/container/external-dns + image: ghcr.io/k8gb-io/external-dns:v0.13.4-azure-ns + # -- external-dns sync interval + interval: "20s" + securityContext: + # -- For more options consult https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#securitycontext-v1-core + runAsUser: 1000 + # -- For ExternalDNS to be able to read Kubernetes and AWS token files + fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files + runAsNonRoot: true + +coredns: + # -- service: refer to https://www.k8gb.io/docs/service_upgrade.html for upgrading CoreDNS service steps + isClusterService: false + serviceType: LoadBalancer + service: + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: nlb + deployment: + # -- Skip CoreDNS creation and uses the one shipped by k8gb instead + skipConfig: true + image: + # -- CoreDNS CRD plugin image + repository: absaoss/k8s_crd + # -- image tag + tag: v0.0.11 + # -- Creates serviceAccount for coredns + serviceAccount: + create: true + name: coredns + +infoblox: + # -- infoblox provider enabled + enabled: false + # -- WAPI address + gridHost: 10.0.0.1 + # -- WAPI version + wapiVersion: 2.3.1 + # -- WAPI port + wapiPort: 443 + # -- use SSL + sslVerify: true + # -- Request Timeout in secconds + httpRequestTimeout: 20 + # -- Size of connections pool + httpPoolConnections: 10 + +route53: + # -- Enable Route53 provider + enabled: false + # -- Route53 ZoneID + hostedZoneID: ZXXXSSS + # -- specify IRSA Role in AWS ARN format or disable it by setting to `null` + irsaRole: arn:aws:iam::111111:role/external-dns + # -- specify IRSA Role in AWS ARN format for assume role permissions or disable it by setting to `null` + assumeRoleArn: null + # -- alternatively specify the secret name with static credentials for IAM user (make sure this user has limited privileges) + # this can be useful when IRSA is not present or when using say Azure cluster and Route53 + # docs: https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/aws.md#create-iam-user-and-attach-the-policy + secret: null + +ns1: + # -- Enable NS1 provider + enabled: false + # -- optional custom NS1 API endpoint for on-prem setups + # endpoint: https://api.nsone.net/v1/ + ignoreSSL: false + +rfc2136: + enabled: false + rfc2136Opts: + - host: host.k3d.internal + - port: 1053 + rfc2136auth: + insecure: + enabled: false + tsig: + enabled: true + tsigCreds: + - tsig-secret-alg: hmac-sha256 + - tsig-keyname: externaldns-key + gssTsig: + enabled: false + kerberosConfigMap: kerberos-config + gssTsigCreds: + - kerberos-username: ad-user + - kerberos-password: ad-user-pass + - kerberos-realm: ad-domain-realm + +cloudflare: + # -- Enable Cloudflare provider + enabled: false + # -- Cloudflare Zone ID + # follow https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/ + # to find your zoneID value + zoneID: replaceme + # -- Configure how many DNS records to fetch per request + # see https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/cloudflare.md#throttling + dnsRecordsPerPage: 5000 + +openshift: + # -- Install OpenShift specific RBAC + enabled: false + +tracing: + # -- if the application should be sending the traces to OTLP collector (env var `TRACING_ENABLED`) + enabled: false + + # -- should the Jaeger be deployed together with the k8gb operator? In case of using another OpenTracing solution, + # make sure that configmap for OTEL agent has the correct exporters set up (`tracing.otelConfig`). + deployJaeger: false + + # -- `host:port` where the spans from the applications (traces) should be sent, sets the `OTEL_EXPORTER_OTLP_ENDPOINT` env var + # This is not the final destination where all the traces are going. Otel collector has its configuration in the associated configmap (`tracing.otelConfig`). + endpoint: localhost:4318 + + # -- float representing the ratio of how often the span should be kept/dropped (env var `TRACING_SAMPLING_RATIO`) + # if not specified, the AlwaysSample will be used which is the same as 1.0. `0.1` would mean that 10% of samples will be kept + samplingRatio: null + + # -- configuration for OTEL collector, this will be represented as configmap called `agent-config` + otelConfig: null + + sidecarImage: + # -- OpenTelemetry collector into which the k8gb operator sends the spans. It can be further configured to send its data + # to somewhere else using exporters (Jaeger for instance) + repository: otel/opentelemetry-collector + tag: 0.57.2 + pullPolicy: Always + + jaegerImage: + # -- if `tracing.deployJaeger==true` this image will be used in the deployment for Jaeger + repository: jaegertracing/all-in-one + tag: 1.37.0 + pullPolicy: Always diff --git a/packs/k8gb-0.12.2/logo.png b/packs/k8gb-0.12.2/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b387a45addd048397e3b0c9a907b64715f25f00f GIT binary patch literal 2681 zcmY*bc|2768$Ls_lr2k!iJ_?B8cWt;kOpJ2GcoE~XK3uk*h(2GHzdg#*>kToODK%B z$d?ZSNr3A+1^^65 z>L<1Xo%+Gy0D#|!z=0neXI5q}G%Hx@ADOcN^si$9$4@q-fb(C>mSz5SzmS!9gV4AT z05~MV4iJ$2K!W9lBRV*doh&U7o`L>wcYL4+0UqHW#8v_N5eOFaCy?Et5&nJwA&3a1 z+;;|oh1q2lIp}u^*%vA2WN8CE8%QERwcx67RXGDbC={ws!h0d?P^LfRtQ}JB5}6!? zP*DjF4~K`Jh6j?oRn&BKbyZZ=Rn*m$Sq$Zn$N;i?gmOU0@qbMI>w_YMc#?=gWMW_d zl8t#FZ3cW`mq~8c$A_7t&N!g?lQQ`Iu(RM7 z-{!|cmX%xUZDPWV%AVABP;|EMK2?n=OT0snIEm;n;}bFA&M_64;+|?&4tpnbTL9Mq zinqG&clLo=r3Iu;2mEQ|ut?VnW#tks%wqVJWu)tF>l35q!K~bwvGu$y>hgMY-Zxfk zVO)c5-V1elSIn77EAtqIVe9j42n^dKSHwyV&Uf?hgWdL?d~Wi2F++~Z^?Jqe)bhPm zH7q^q_ti;5&9>f#~FpD~9jB;}dzaU~8ezozx$IJ# zn<%8ppoEHMxD4MzKMIG>hMx{^m-mgYa61yG>LCMGn16r34JomBzM!+NKM^0eF)IW0 zd1AJCzyLY;(F{JYI9^tFv=OFDqhMn@wQ-KeTP~(uT!^^*Sf%RV#QWmBz1X&?bA_bP z+9DGPS|pdWu(ao+(dk^YX|T0qIeN$`bxd6DVrKfT7i!3lPUS(V2}B1L4p9kmniPfR z0z%LlIjiALZh!Mux?-bvwzNzUdMvj29G}II3-3(8lKmyFx&r~!X?bl3O|X$zWCd4u3&qUUuEwS$d}!;^q6R2u6lWDJgCH+Y zMVwTMK9}4zye=C2Sr&rv=3dKo%YXWeICr1(z=Bq(ULN*vFDd3k@^*9?l`%d#kgAixx#JM2J-G{pG+ zkgQJxa{Q9S%r__s_7x~2mE&&Nd>HD}L&M0a)nU)?$vX1%A-kWXwACpEUtSGNM+MPO zw=&T)8b`{2uhk~e|Pb0S!w124O%Gfe>Eq#5U6@(BUU|@sFh4`qV$XQwWy8T|FKAGqh0kk`berbeZ%P9hqDo41 zO%f#?E{N2KC3A0h4;a>-Es4!iN>G|3q=h<*2J)v}t+P}&E+ors6Qkn$6c^GlK{G-r z6JI{@3V$%vpudG&#H9rpQ* z0!$+Y;%mgiwC+mYf1K1*MqTdSFD8S14@7bxzh?A-rNJLxfD4?j%Dd;)yw-Mpvllfg zrtc|nD({<3HXv^YFgx-j!0N zCcQPnJA+=gtJ&{T>@H~gGCk&&r*1^vS!aDKBS5ZO_sVR7??ShI~O-w`>$uZiIX*6 z|GH2p6S7BTCM3)Exol?i%h}jjSip`iN?@I~`ERh%Jm}mRCUQ!!>@L=IpDG z*ZYac{wPZ6W@kr_H*KYPd%)c}C$xmJk#{fOqjCnG3)^n(7w8eY?~Zz3;wICvRN=4% zKN<1X4)0{@(ksi@rdZ|gl=NqIbVmmlLh!Sw#PnXUH7l(Yqlh7uGWdkAXXc)(VMQEwMJ+Z-`SIrG4MR%A z6-yMup{*S~RHwg3B1*vlY literal 0 HcmV?d00001 diff --git a/packs/k8gb-0.12.2/pack.json b/packs/k8gb-0.12.2/pack.json new file mode 100644 index 00000000..d398aaa8 --- /dev/null +++ b/packs/k8gb-0.12.2/pack.json @@ -0,0 +1,17 @@ +{ + "name": "k8gb", + "displayName": "k8gb", + "annotations": { + "description": "Kubernetes Global Balancer", + "contributor": "spectrocloud" + }, + "version": "0.12.2", + "charts": [ + "charts/k8gb-0.12.2.tgz" + ], + "layer": "addon", + "addonType": "system app", + "cloudTypes": [ + "all" + ] +} diff --git a/packs/k8gb-0.12.2/schema.yaml b/packs/k8gb-0.12.2/schema.yaml new file mode 100644 index 00000000..df479c95 --- /dev/null +++ b/packs/k8gb-0.12.2/schema.yaml @@ -0,0 +1,2 @@ +pack.namespace: + schema: '{{ required | format "${string}" }}' \ No newline at end of file diff --git a/packs/k8gb-0.12.2/values.yaml b/packs/k8gb-0.12.2/values.yaml new file mode 100644 index 00000000..e24ca1fa --- /dev/null +++ b/packs/k8gb-0.12.2/values.yaml @@ -0,0 +1,211 @@ +pack: + content: + images: + - image: docker.io/absaoss/k8gb:v0.12.2 + - image: absaoss/k8s_crd:v0.0.11 + - image: ghcr.io/k8gb-io/external-dns:v0.13.4-azure-ns + - image: otel/opentelemetry-collector:0.57.2 + - image: jaegertracing/all-in-one:1.37.0 + + namespace: "k8gb" + +charts: + k8gb: + global: + # -- Reference to one or more secrets to be used when pulling images + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + imagePullSecrets: [] + # - name: "image-pull-secret" + + k8gb: + # -- image repository + imageRepo: "docker.io/absaoss/k8gb" + # -- ( string ) image tag defaults to Chart.AppVersion, see Chart.yaml, but can be overrided with imageTag key + imageTag: + # -- whether it should also deploy the gslb and dnsendpoints CRDs + deployCrds: true + # -- whether it should also deploy the service account, cluster role and cluster role binding + deployRbac: true + # -- dnsZone controlled by gslb + dnsZone: "cloud.example.com" + # -- Negative TTL for SOA record + dnsZoneNegTTL: 300 + # -- main zone which would contain gslb zone to delegate + edgeDNSZone: "example.com" # main zone which would contain gslb zone to delegate + # -- host/ip[:port] format is supported here where port defaults to 53 + edgeDNSServers: + # -- use this DNS server as a main resolver to enable cross k8gb DNS based communication + # Defaults to Route 53 Resolver (see: https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#AmazonDNS) + - "169.254.169.253" + # -- used for places where we need to distinguish between different Gslb instances + clusterGeoTag: "eu" + # -- comma-separated list of external gslb geo tags to pair with + extGslbClustersGeoTags: "us" + # -- Reconcile time in seconds + reconcileRequeueSeconds: 30 + # -- Extra CoreDNS plugins to be enabled (yaml object) + coredns: + extra_plugins: "" + log: + # -- log format (simple,json) + format: simple # log format (simple,json) + # -- log level (panic,fatal,error,warn,info,debug,trace) + level: info # log level (panic,fatal,error,warn,info,debug,trace) + # -- Enable SplitBrain check (Infoblox only) + splitBrainCheck: false + # -- Metrics server address + metricsAddress: "0.0.0.0:8080" + securityContext: + # -- For more options consult https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#securitycontext-v1-core + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + runAsUser: 1000 + # -- Exposing metrics + exposeMetrics: false + # -- enable ServiceMonitor + serviceMonitor: + enabled: false + + externaldns: + # -- `.spec.template.spec.dnsPolicy` for ExternalDNS deployment + dnsPolicy: "ClusterFirst" + # -- external-dns image repo:tag + # It is important to use the image from k8gb external-dns fork to get the full + # functionality. See links below + # https://github.com/k8gb-io/external-dns + # https://github.com/k8gb-io/external-dns/pkgs/container/external-dns + image: ghcr.io/k8gb-io/external-dns:v0.13.4-azure-ns + # -- external-dns sync interval + interval: "20s" + securityContext: + # -- For more options consult https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#securitycontext-v1-core + runAsUser: 1000 + # -- For ExternalDNS to be able to read Kubernetes and AWS token files + fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files + runAsNonRoot: true + + coredns: + # -- service: refer to https://www.k8gb.io/docs/service_upgrade.html for upgrading CoreDNS service steps + isClusterService: false + serviceType: LoadBalancer + service: + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: nlb + deployment: + # -- Skip CoreDNS creation and uses the one shipped by k8gb instead + skipConfig: true + image: + # -- CoreDNS CRD plugin image + repository: absaoss/k8s_crd + # -- image tag + tag: v0.0.11 + # -- Creates serviceAccount for coredns + serviceAccount: + create: true + name: coredns + + infoblox: + # -- infoblox provider enabled + enabled: false + # -- WAPI address + gridHost: 10.0.0.1 + # -- WAPI version + wapiVersion: 2.3.1 + # -- WAPI port + wapiPort: 443 + # -- use SSL + sslVerify: true + # -- Request Timeout in secconds + httpRequestTimeout: 20 + # -- Size of connections pool + httpPoolConnections: 10 + + route53: + # -- Enable Route53 provider + enabled: false + # -- Route53 ZoneID + hostedZoneID: ZXXXSSS + # -- specify IRSA Role in AWS ARN format or disable it by setting to `null` + irsaRole: null + # -- specify IRSA Role in AWS ARN format for assume role permissions or disable it by setting to `null` + assumeRoleArn: null + # -- alternatively specify the secret name with static credentials for IAM user (make sure this user has limited privileges) + # this can be useful when IRSA is not present or when using say Azure cluster and Route53 + # docs: https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/aws.md#create-iam-user-and-attach-the-policy + secret: null + + ns1: + # -- Enable NS1 provider + enabled: false + # -- optional custom NS1 API endpoint for on-prem setups + # endpoint: https://api.nsone.net/v1/ + ignoreSSL: false + + rfc2136: + enabled: false + rfc2136Opts: + - host: host.k3d.internal + - port: 1053 + rfc2136auth: + insecure: + enabled: false + tsig: + enabled: true + tsigCreds: + - tsig-secret-alg: hmac-sha256 + - tsig-keyname: externaldns-key + gssTsig: + enabled: false + kerberosConfigMap: kerberos-config + gssTsigCreds: + - kerberos-username: ad-user + - kerberos-password: ad-user-pass + - kerberos-realm: ad-domain-realm + + cloudflare: + # -- Enable Cloudflare provider + enabled: false + # -- Cloudflare Zone ID + # follow https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/ + # to find your zoneID value + zoneID: replaceme + # -- Configure how many DNS records to fetch per request + # see https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/cloudflare.md#throttling + dnsRecordsPerPage: 5000 + + openshift: + # -- Install OpenShift specific RBAC + enabled: false + + tracing: + # -- if the application should be sending the traces to OTLP collector (env var `TRACING_ENABLED`) + enabled: false + + # -- should the Jaeger be deployed together with the k8gb operator? In case of using another OpenTracing solution, + # make sure that configmap for OTEL agent has the correct exporters set up (`tracing.otelConfig`). + deployJaeger: false + + # -- `host:port` where the spans from the applications (traces) should be sent, sets the `OTEL_EXPORTER_OTLP_ENDPOINT` env var + # This is not the final destination where all the traces are going. Otel collector has its configuration in the associated configmap (`tracing.otelConfig`). + endpoint: localhost:4318 + + # -- float representing the ratio of how often the span should be kept/dropped (env var `TRACING_SAMPLING_RATIO`) + # if not specified, the AlwaysSample will be used which is the same as 1.0. `0.1` would mean that 10% of samples will be kept + samplingRatio: null + + # -- configuration for OTEL collector, this will be represented as configmap called `agent-config` + otelConfig: null + + sidecarImage: + # -- OpenTelemetry collector into which the k8gb operator sends the spans. It can be further configured to send its data + # to somewhere else using exporters (Jaeger for instance) + repository: otel/opentelemetry-collector + tag: 0.57.2 + pullPolicy: Always + + jaegerImage: + # -- if `tracing.deployJaeger==true` this image will be used in the deployment for Jaeger + repository: jaegertracing/all-in-one + tag: 1.37.0 + pullPolicy: Always From 7abf49b23c8c3f70f8da573ed2b1392e883f39ad Mon Sep 17 00:00:00 2001 From: Appdynamics Release Management Date: Thu, 2 May 2024 11:29:52 +0000 Subject: [PATCH 10/22] AppD charts appdynamics-operators 1.21.368 --- .../appdynamics-operators-1.21.368/README.md | 21 + .../charts/appdynamics-operators-1.21.368.tgz | Bin 0 -> 104417 bytes .../charts/appdynamics-operators/Chart.lock | 12 + .../charts/appdynamics-operators/Chart.yaml | 34 + .../charts/appdynamics-operators/LICENSE | 11 + .../appdynamics-cloud-operator/.helmignore | 23 + .../appdynamics-cloud-operator/Chart.yaml | 18 + .../templates/manager/manager-config.yaml | 17 + .../templates/manager/manager.yaml | 95 + .../templates/post-install-job.yaml | 65 + ...ppdynamics_cloud_operator_clusterrole.yaml | 51 + ...cs_cloud_operator_clusterrole_binding.yaml | 12 + .../rbac/appdynamics_cloud_operator_role.yaml | 44 + ...pdynamics_cloud_operator_role_binding.yaml | 13 + .../rbac/auth_proxy_client_clusterrole.yaml | 10 + .../templates/rbac/auth_proxy_role.yaml | 18 + .../rbac/auth_proxy_role_binding.yaml | 13 + .../templates/rbac/auth_proxy_service.yaml | 14 + .../templates/rbac/leader_election_role.yaml | 38 + .../rbac/leader_election_role_binding.yaml | 13 + .../templates/rbac/role.yaml | 269 + .../templates/rbac/role_binding.yaml | 12 + .../templates/rbac/service_account.yaml | 5 + .../tests/test_health_connection.yaml | 52 + .../templates/tests/test_health_service.yaml | 26 + .../test_metrics_clusterrole_binding.yaml | 26 + .../tests/test_metrics_connection.yaml | 44 + .../values.schema.json | 92 + .../appdynamics-cloud-operator/values.yaml | 30 + .../charts/appdynamics-smartagent/.helmignore | 24 + .../charts/appdynamics-smartagent/Chart.yaml | 8 + .../templates/NOTES.txt | 30 + .../templates/_helpers.tpl | 62 + .../templates/cluster_role.yaml | 21 + .../templates/cluster_role_binding.yaml | 14 + .../templates/configmap.yaml | 40 + .../templates/deployment.yaml | 82 + .../templates/secret.yaml | 12 + .../templates/serviceaccount.yaml | 13 + .../__snapshot__/deployment_test.yaml.snap | 64 + .../tests/configmap_test.yaml | 43 + .../tests/deployment_test.yaml | 59 + .../tests/role_test.yaml | 106 + .../tests/rolebinding_test.yaml | 79 + .../tests/secret_test.yaml | 49 + .../tests/serviceaccount_test.yaml | 44 + .../tests/values/values.yaml | 104 + .../charts/appdynamics-smartagent/values.yaml | 237 + .../charts/opentelemetry-operator/.helmignore | 25 + .../opentelemetry-operator/CONTRIBUTING.md | 11 + .../charts/opentelemetry-operator/Chart.yaml | 13 + .../charts/opentelemetry-operator/LICENSE.txt | 201 + .../charts/opentelemetry-operator/README.md | 273 + .../opentelemetry-operator/UPGRADING.md | 36 + ...t-manager-disable-nameoverride-values.yaml | 5 + .../ci/cert-manager-disable-values.yaml | 3 + .../ci/nameoverride-values.yaml | 1 + .../ci/secret-name-nameoverride-values.yaml | 4 + .../ci/secret-name-values.yaml | 2 + .../crd-opentelemetry.io_opampbridges.yaml | 2823 +++++++ .../crds/crd-opentelemetrycollector.yaml | 7092 +++++++++++++++++ .../crd-opentelemetryinstrumentation.yaml | 1627 ++++ .../opentelemetry-operator/examples/README.md | 7 + .../operator-webhook-with-cert-manager.yaml | 184 + .../default/rendered/certmanager.yaml | 41 + .../default/rendered/clusterrole.yaml | 293 + .../default/rendered/clusterrolebinding.yaml | 42 + .../examples/default/rendered/deployment.yaml | 104 + .../examples/default/rendered/role.yaml | 42 + .../default/rendered/rolebinding.yaml | 22 + .../examples/default/rendered/service.yaml | 49 + .../default/rendered/serviceaccount.yaml | 14 + .../tests/test-certmanager-connection.yaml | 37 + .../tests/test-service-connection.yaml | 74 + .../examples/default/values.yaml | 1 + .../opentelemetry-operator/kuttl-test.yaml | 4 + .../templates/NOTES.txt | 4 + .../templates/_helpers.tpl | 117 + .../operator-webhook-with-cert-manager.yaml | 233 + .../admission-webhooks/operator-webhook.yaml | 265 + .../templates/certmanager.yaml | 46 + .../templates/clusterrole.yaml | 282 + .../templates/clusterrolebinding.yaml | 36 + .../templates/deployment.yaml | 166 + .../opentelemetry-operator/templates/pdb.yaml | 21 + .../templates/prometheusrule.yaml | 42 + .../templates/role.yaml | 38 + .../templates/rolebinding.yaml | 18 + .../templates/service.yaml | 43 + .../templates/serviceaccount.yaml | 16 + .../templates/servicemonitor.yaml | 29 + .../tests/test-certmanager-connection.yaml | 42 + .../tests/test-service-connection.yaml | 85 + .../templates/verticalpodautoscaler.yaml | 38 + .../opentelemetry-operator/values.schema.json | 1852 +++++ .../charts/opentelemetry-operator/values.yaml | 274 + .../appdynamics-operators/templates/NOTES.txt | 31 + .../templates/_helpers.tpl | 63 + .../opentelemetry_operator_openshift_scc.yaml | 22 + .../charts/appdynamics-operators/values.yaml | 25 + packs/appdynamics-operators-1.21.368/logo.png | Bin 0 -> 47881 bytes .../appdynamics-operators-1.21.368/pack.json | 18 + .../values.yaml | 37 + 103 files changed, 19042 insertions(+) create mode 100644 packs/appdynamics-operators-1.21.368/README.md create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators-1.21.368.tgz create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/Chart.lock create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/Chart.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/LICENSE create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/.helmignore create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/Chart.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/manager/manager-config.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/manager/manager.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/post-install-job.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_clusterrole.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_clusterrole_binding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_role.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_role_binding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_client_clusterrole.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_role.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_role_binding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_service.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/leader_election_role.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/leader_election_role_binding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/role.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/role_binding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/service_account.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_health_connection.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_health_service.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_metrics_clusterrole_binding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_metrics_connection.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/values.schema.json create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/.helmignore create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/Chart.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/NOTES.txt create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/_helpers.tpl create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/cluster_role.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/cluster_role_binding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/configmap.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/deployment.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/secret.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/serviceaccount.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/__snapshot__/deployment_test.yaml.snap create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/configmap_test.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/deployment_test.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/role_test.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/rolebinding_test.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/secret_test.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/serviceaccount_test.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/values/values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/.helmignore create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/CONTRIBUTING.md create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/Chart.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/LICENSE.txt create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/README.md create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/UPGRADING.md create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/cert-manager-disable-nameoverride-values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/cert-manager-disable-values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/nameoverride-values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/secret-name-nameoverride-values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/secret-name-values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetry.io_opampbridges.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetrycollector.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetryinstrumentation.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/README.md create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/admission-webhooks/operator-webhook-with-cert-manager.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/certmanager.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/clusterrole.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/clusterrolebinding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/deployment.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/role.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/rolebinding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/service.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/serviceaccount.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/tests/test-certmanager-connection.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/tests/test-service-connection.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/kuttl-test.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/NOTES.txt create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/_helpers.tpl create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/admission-webhooks/operator-webhook-with-cert-manager.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/admission-webhooks/operator-webhook.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/certmanager.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/clusterrole.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/clusterrolebinding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/deployment.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/pdb.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/prometheusrule.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/role.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/rolebinding.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/service.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/serviceaccount.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/servicemonitor.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/tests/test-certmanager-connection.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/tests/test-service-connection.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/verticalpodautoscaler.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/values.schema.json create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/NOTES.txt create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/_helpers.tpl create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/opentelemetry_operator_openshift_scc.yaml create mode 100644 packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/values.yaml create mode 100644 packs/appdynamics-operators-1.21.368/logo.png create mode 100644 packs/appdynamics-operators-1.21.368/pack.json create mode 100644 packs/appdynamics-operators-1.21.368/values.yaml diff --git a/packs/appdynamics-operators-1.21.368/README.md b/packs/appdynamics-operators-1.21.368/README.md new file mode 100644 index 00000000..7e5cc596 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/README.md @@ -0,0 +1,21 @@ +## The Appdynamics Operator Cloud Helm Charts +An Add-on pack for Spectro Cloud to use the monitoring of k8s cluster with AppDynamics collectors. + +## Appdynamics Cloud Helm Charts +This repository maintains helm charts for installing Appdynamics Cloud Operators. + + +## Parameters +| Parameter | Description | +|-----------|-------------| +| clusterName | String to specify the name of the k8s cluster | +| endpoint | The endpoint Tenant to which you want to send the data to. Please refer the product guide link from References for more details | +| clientId | clientId of your Tenant . Please refer the product guide link from References for more details | +| clientSecret | clientSecret of your Tenant. Please refer the product guide link from References for more details | +| tokenUrl | tokenUrl of your Tenant. Please refer the product guide link from References for more details | +| tenantId | tenantId of your Tenant. Please refer the product guide link from References for more details | + + +## References +Here is the complete product guide about the AppDynamics collectors. +https://docs.appdynamics.com/fso/cloud-native-app-obs/en/kubernetes-and-app-service-monitoring/install-kubernetes-and-app-service-monitoring \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators-1.21.368.tgz b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators-1.21.368.tgz new file mode 100644 index 0000000000000000000000000000000000000000..89dd34db600f899ca2ffdb2bffaecae8b8561fa9 GIT binary patch literal 104417 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 literal 0 HcmV?d00001 diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/Chart.lock b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/Chart.lock new file mode 100644 index 00000000..e31897fb --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/Chart.lock @@ -0,0 +1,12 @@ +dependencies: +- name: appdynamics-cloud-operator + repository: "" + version: 1.21.0 +- name: opentelemetry-operator + repository: "" + version: 0.43.0 +- name: appdynamics-smartagent + repository: https://artifactory.bare.appdynamics.com/artifactory/cosmosx-helm + version: 24.4.73 +digest: sha256:0cc077f81c6abed16e86812af71248b03134e8094f89825c26b02c53437664bb +generated: "2024-04-25T19:14:09.981435824Z" diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/Chart.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/Chart.yaml new file mode 100644 index 00000000..4416317c --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/Chart.yaml @@ -0,0 +1,34 @@ +apiVersion: v2 +appVersion: 1.21.368 +dependencies: +- condition: appdynamics-cloud-operator.enabled + name: appdynamics-cloud-operator + repository: "" + version: 1.21.0 +- condition: opentelemetry-operator.enabled + name: opentelemetry-operator + repository: "" + version: 0.43.0 +- condition: appdynamics-smartagent.enabled + name: appdynamics-smartagent + repository: https://artifactory.bare.appdynamics.com/artifactory/cosmosx-helm + version: 24.4.73 +description: Helm Charts for installing Appdynamics Operators +home: https://appdynamics.com +icon: https://raw.githubusercontent.com/CiscoDevNet/appdynamics-charts/master/logo.png +keywords: +- appdynamics +- cloud +- operator +- cluster +- kubernetes +- monitoring +- pod +- deployment +- orchestration +maintainers: +- email: support@appdynamics.com + name: AppDynamics +name: appdynamics-operators +type: application +version: 1.21.368 diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/LICENSE b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/LICENSE new file mode 100644 index 00000000..d17050b1 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/LICENSE @@ -0,0 +1,11 @@ +APPDYNAMICS +END USER LICENSE AGREEMENT + +By accessing the Software herein, you (and the organization you represent) ("You") acknowledge and agree that the use +of the Software and open source software are governed by (1) the General Terms found at +https://www.cisco.com/c/dam/en_us/about/doing_business/legal/Cisco_General_Terms.pdf and the applicable Product +Specific Terms found at https://www.cisco.com/c/en/us/about/legal/cloud-and-software/software-terms.html or (2) any +other superseding agreement between AppDynamics, or its parent company Cisco Systems, Inc., as applicable, and You. +References to End User in any superseding agreement shall mean You. + +AppDynamics Proprietary and Confidential * Revision 2024.03 diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/.helmignore b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/Chart.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/Chart.yaml new file mode 100644 index 00000000..8d32fa0c --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +appVersion: 24.4.0 +description: Helm chart for Appdynamics Cloud Operator +home: https://appdynamics.com +icon: https://raw.githubusercontent.com/CiscoDevNet/appdynamics-charts/master/logo.png +keywords: +- appdynamics +- operator +- cluster +- kubernetes +- monitoring +- pod +- deployment +maintainers: +- email: support@appdynamics.com + name: AppDynamics +name: appdynamics-cloud-operator +version: 1.21.0 diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/manager/manager-config.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/manager/manager-config.yaml new file mode 100644 index 00000000..1d1624e8 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/manager/manager-config.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: manager-config + namespace: {{ .Release.Namespace }} +data: + apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 + kind: ControllerManagerConfig + health: | + healthProbeBindAddress: :8081 + metrics: | + bindAddress: 127.0.0.1:8080 + webhook: | + port: 9443 + leaderElection: | + leaderElect: true + resourceName: 42f55d18.appdynamics.com \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/manager/manager.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/manager/manager.yaml new file mode 100644 index 00000000..87982eab --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/manager/manager.yaml @@ -0,0 +1,95 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-cloud-operator" | trunc 63 }} + namespace: {{ .Release.Namespace }} + labels: + control-plane: appdynamics-cloud-operator +spec: + selector: + matchLabels: + control-plane: appdynamics-cloud-operator + replicas: 1 + template: + metadata: + labels: + control-plane: appdynamics-cloud-operator + {{- if .Values.operatorPod.labels -}} + {{- toYaml .Values.operatorPod.labels | nindent 8 }} + {{- end }} + annotations: + kubectl.kubernetes.io/default-container: manager + {{- if .Values.operatorPod.annotations -}} + {{- toYaml .Values.operatorPod.annotations | nindent 8 }} + {{- end }} + spec: + containers: + - name: kube-rbac-proxy + image: {{ .Values.kubeRbacProxy.image | default "gcr.io/kubebuilder/kube-rbac-proxy:v0.15.0" }} + imagePullPolicy: {{ .Values.kubeRbacProxy.imagePullPolicy | default "IfNotPresent" }} + args: + - "--secure-listen-address=0.0.0.0:8443" + - "--upstream=http://127.0.0.1:8080/" + - "--logtostderr=true" + - "--v=0" + ports: + - containerPort: 8443 + name: https + - name: manager + args: + - --leader-elect + image: {{ .Values.operatorPod.image }} + imagePullPolicy: {{ .Values.operatorPod.imagePullPolicy }} + env: + - name: APPDYNAMICS_OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MANAGE_OPEN_TELEMETRY_CRDS + value: {{ .Values.enableOTelCRDManagement | quote }} + - name: WATCH_CLUSTER + value: {{ eq .Values.watchMode "cluster" | quote }} + {{- if .Values.operatorPod.dev }} + {{- toYaml .Values.operatorPod.dev | nindent 10 }} + {{- end }} + - name: CSAAS_AGENTS_CONTROLLER_ENABLED + value: {{ .Values.enableUnifiedOperator | quote}} + securityContext: + allowPrivilegeEscalation: false + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + {{- toYaml .Values.operatorPod.resources | nindent 10 }} + {{- if .Values.operatorPod.priorityClassName }} + priorityClassName: {{ .Values.operatorPod.priorityClassName }} + {{- end }} + imagePullSecrets: + {{- toYaml .Values.operatorPod.imagePullSecrets | nindent 8}} + serviceAccountName: {{ .Values.operatorServiceAccount }} + terminationGracePeriodSeconds: 10 + {{- if .Values.operatorPod.nodeSelector }} + nodeSelector: + {{- toYaml .Values.operatorPod.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.operatorPod.affinity }} + affinity: + {{- toYaml .Values.operatorPod.affinity | nindent 8 }} + {{- end }} + {{- if .Values.operatorPod.tolerations }} + tolerations: + {{- toYaml .Values.operatorPod.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.operatorPod.securityContext }} + securityContext: + {{- toYaml .Values.operatorPod.securityContext | nindent 8 }} + {{- end }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/post-install-job.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/post-install-job.yaml new file mode 100644 index 00000000..3131ee52 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/post-install-job.yaml @@ -0,0 +1,65 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-crd-validator" | trunc 63 }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": post-install + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded,hook-failed +spec: + backoffLimit: 0 + template: + metadata: + name: {{ printf "%s-%s" .Release.Name "appdynamics-crd-validator" | trunc 63 }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + {{- if .Values.operatorPod.labels -}} + {{- toYaml .Values.operatorPod.labels | nindent 8 }} + {{- end }} + {{- if .Values.operatorPod.annotations }} + annotations: + {{- toYaml .Values.operatorPod.annotations | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ .Values.operatorServiceAccount }} + restartPolicy: Never + containers: + - name: post-install-job + image: {{ .Values.operatorPod.image }} + imagePullPolicy: {{ .Values.operatorPod.imagePullPolicy }} + command: ["/crd-validator"] + env: + - name: MANAGE_OPEN_TELEMETRY_CRDS + value: {{ .Values.enableOTelCRDManagement | quote }} + - name: CSAAS_AGENTS_CONTROLLER_ENABLED + value: {{ .Values.enableUnifiedOperator | quote}} + imagePullSecrets: + {{- toYaml .Values.operatorPod.imagePullSecrets | nindent 8}} + {{- if .Values.operatorPod.priorityClassName }} + priorityClassName: {{ .Values.operatorPod.priorityClassName }} + {{- end }} + {{- if .Values.operatorPod.nodeSelector }} + nodeSelector: + {{- toYaml .Values.operatorPod.nodeSelector | nindent 8 }} + {{- end }} + {{- if .Values.operatorPod.affinity }} + affinity: + {{- toYaml .Values.operatorPod.affinity | nindent 8 }} + {{- end }} + {{- if .Values.operatorPod.tolerations }} + tolerations: + {{- toYaml .Values.operatorPod.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.operatorPod.securityContext }} + securityContext: + {{- toYaml .Values.operatorPod.securityContext | nindent 8 }} + {{- end }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_clusterrole.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_clusterrole.yaml new file mode 100644 index 00000000..54b70ec6 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_clusterrole.yaml @@ -0,0 +1,51 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: appdynamics-cloud-operator-clusterrole +rules: +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - create + - update +{{ if eq .Values.watchMode "cluster"}} +- apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - get + - create + - update + - list + - watch + - delete +- apiGroups: + - apps + resources: + - deployments + - daemonsets + verbs: + - get + - create + - update + - list + - watch +{{ if .Values.enableUnifiedOperator }} +- apiGroups: + - "" + resources: + - services + verbs: + - get + - create + - update + - list + - watch + - delete +{{ end }} +{{ end }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_clusterrole_binding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_clusterrole_binding.yaml new file mode 100644 index 00000000..1ed009bc --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_clusterrole_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: appdynamics-cloud-operator-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: appdynamics-cloud-operator-clusterrole +subjects: +- kind: ServiceAccount + name: {{ .Values.operatorServiceAccount }} + namespace: {{ .Release.Namespace }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_role.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_role.yaml new file mode 100644 index 00000000..18df4ff2 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_role.yaml @@ -0,0 +1,44 @@ +{{ if eq .Values.watchMode "namespace" }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: appdynamics-cloud-operator-role + namespace: {{ .Release.Namespace }} +rules: +- apiGroups: + - "" + resources: + - configmaps + - secrets + verbs: + - get + - create + - update + - list + - watch + - delete +- apiGroups: + - apps + resources: + - daemonsets + - deployments + verbs: + - get + - create + - update + - list + - watch +{{ if .Values.enableUnifiedOperator }} +- apiGroups: + - "" + resources: + - services + verbs: + - get + - create + - update + - list + - watch + - delete +{{ end }} +{{ end }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_role_binding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_role_binding.yaml new file mode 100644 index 00000000..a23a14b9 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/appdynamics_cloud_operator_role_binding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: appdynamics-cloud-operator-rolebinding + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: appdynamics-cloud-operator-role +subjects: + - kind: ServiceAccount + name: {{ .Values.operatorServiceAccount }} + namespace: {{ .Release.Namespace }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_client_clusterrole.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_client_clusterrole.yaml new file mode 100644 index 00000000..115cd58d --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_client_clusterrole.yaml @@ -0,0 +1,10 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: appdynamics-cloud-operator-metrics-reader + namespace: {{ .Release.Namespace }} +rules: +- nonResourceURLs: + - "/metrics" + verbs: + - get diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_role.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_role.yaml new file mode 100644 index 00000000..90daacc3 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_role.yaml @@ -0,0 +1,18 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: appdynamics-cloud-operator-proxy-role + namespace: {{ .Release.Namespace }} +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_role_binding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 00000000..26a18c2f --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: appdynamics-cloud-operator-proxy-rolebinding + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: appdynamics-cloud-operator-proxy-role +subjects: +- kind: ServiceAccount + name: {{ .Values.operatorServiceAccount }} + namespace: {{ .Release.Namespace }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_service.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_service.yaml new file mode 100644 index 00000000..8a8a0f6a --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/auth_proxy_service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: appdynamics-cloud-operator + name: appdynamics-cloud-operator-metrics-service + namespace: {{ .Release.Namespace }} +spec: + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: appdynamics-cloud-operator diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/leader_election_role.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/leader_election_role.yaml new file mode 100644 index 00000000..645c9615 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/leader_election_role.yaml @@ -0,0 +1,38 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: leader-election-role + namespace: {{ .Release.Namespace }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/leader_election_role_binding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/leader_election_role_binding.yaml new file mode 100644 index 00000000..d9d72e04 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/leader_election_role_binding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: leader-election-rolebinding + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: +- kind: ServiceAccount + name: {{ .Values.operatorServiceAccount }} + namespace: {{ .Release.Namespace }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/role.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/role.yaml new file mode 100644 index 00000000..c8d36bdf --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/role.yaml @@ -0,0 +1,269 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: appdynamics-cloud-operator-customresource-clusterrole +rules: +- apiGroups: + - cluster.appdynamics.com + resources: + - clustermons + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cluster.appdynamics.com + resources: + - clustermons/finalizers + verbs: + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - clustermons/status + verbs: + - get + - patch + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - dbcollectors + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cluster.appdynamics.com + resources: + - dbcollectors/finalizers + verbs: + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - dbcollectors/status + verbs: + - get + - patch + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - dbconfigs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cluster.appdynamics.com + resources: + - dbconfigs/finalizers + verbs: + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - dbconfigs/status + verbs: + - get + - patch + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - containermons + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cluster.appdynamics.com + resources: + - containermons/finalizers + verbs: + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - containermons/status + verbs: + - get + - patch + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - inframons + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cluster.appdynamics.com + resources: + - inframons/finalizers + verbs: + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - inframons/status + verbs: + - get + - patch + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - logcollectors + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cluster.appdynamics.com + resources: + - logcollectors/finalizers + verbs: + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - logcollectors/status + verbs: + - get + - patch + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - servermons + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cluster.appdynamics.com + resources: + - servermons/finalizers + verbs: + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - servermons/status + verbs: + - get + - patch + - update +{{ if .Values.enableUnifiedOperator }} +- apiGroups: + - cluster.appdynamics.com + resources: + - clusteragents + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cluster.appdynamics.com + resources: + - clusteragents/finalizers + verbs: + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - clusteragents/status + verbs: + - get + - patch + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - infravizs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cluster.appdynamics.com + resources: + - infravizs/finalizers + verbs: + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - infravizs/status + verbs: + - get + - patch + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - autoinstrumentationagents + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cluster.appdynamics.com + resources: + - autoinstrumentationagents/finalizers + verbs: + - update +- apiGroups: + - cluster.appdynamics.com + resources: + - autoinstrumentationagents/status + verbs: + - get + - patch + - update +{{ end }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/role_binding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/role_binding.yaml new file mode 100644 index 00000000..6415e319 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: appdynamics-cloud-operator-customresource-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: appdynamics-cloud-operator-customresource-clusterrole +subjects: +- kind: ServiceAccount + name: {{ .Values.operatorServiceAccount }} + namespace: {{ .Release.Namespace }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/service_account.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/service_account.yaml new file mode 100644 index 00000000..71ca7ff3 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/rbac/service_account.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.operatorServiceAccount }} + namespace: {{ .Release.Namespace }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_health_connection.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_health_connection.yaml new file mode 100644 index 00000000..488ccdd2 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_health_connection.yaml @@ -0,0 +1,52 @@ +{{- if .Values.testFramework.enabled }} +apiVersion: v1 +kind: Pod +metadata: + name: "appdynamics-cloud-operator-health-test-connection" + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": test + "helm.sh/hook-weight": "1" + "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded +spec: + containers: + - name: wget + image: "{{ .Values.testFramework.image.repository }}:{{ .Values.testFramework.image.tag }}" + env: + - name: MANAGER_HEALTH_SERVICE_CLUSTERIP + value: "appdynamics-cloud-operator-health-test-service" + - name: MANAGER_HEALTH_SERVICE_PORT + value: "8081" + command: + - sh + - -c + # The following shell script tests if the manager health is ok. + - | + options="--server-response --spider --timeout=10" + + liveness_url="$MANAGER_HEALTH_SERVICE_CLUSTERIP:$MANAGER_HEALTH_SERVICE_PORT/healthz" + liveness_status=$(wget $options $liveness_url 2>&1 | grep "HTTP/" | awk '{print $2}') + if [ "$liveness_status" != "200" ] + then + echo "Liveness check failed" + exit 1 + fi + + readiness_url="$MANAGER_HEALTH_SERVICE_CLUSTERIP:$MANAGER_HEALTH_SERVICE_PORT/readyz" + readiness_status=$(wget $options $readiness_url 2>&1 | grep "HTTP/" | awk '{print $2}') + if [ "$readiness_status" != "200" ] + then + echo "Readiness check failed" + exit 1 + fi + + exit 0 + restartPolicy: Never +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_health_service.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_health_service.yaml new file mode 100644 index 00000000..f847e7cd --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_health_service.yaml @@ -0,0 +1,26 @@ +{{- if .Values.testFramework.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: "appdynamics-cloud-operator-health-test-service" + namespace: {{ .Release.Namespace }} + labels: + control-plane: appdynamics-cloud-operator + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": test + "helm.sh/hook-weight": "0" + "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failure +spec: + ports: + - name: healthz + port: 8081 + targetPort: 8081 + selector: + control-plane: appdynamics-cloud-operator +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_metrics_clusterrole_binding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_metrics_clusterrole_binding.yaml new file mode 100644 index 00000000..6cb3276f --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_metrics_clusterrole_binding.yaml @@ -0,0 +1,26 @@ +{{- if .Values.testFramework.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: "appdynamics-cloud-operator-metrics-test-clusterrole-binding" + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": test + "helm.sh/hook-weight": "2" + "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failure +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: appdynamics-cloud-operator-metrics-reader +subjects: + - kind: ServiceAccount + name: {{ .Values.operatorServiceAccount }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_metrics_connection.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_metrics_connection.yaml new file mode 100644 index 00000000..79ad4828 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/templates/tests/test_metrics_connection.yaml @@ -0,0 +1,44 @@ +{{- if .Values.testFramework.enabled }} +apiVersion: v1 +kind: Pod +metadata: + name: "appdynamics-cloud-operator-metrics-test-connection" + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": test + "helm.sh/hook-weight": "3" + "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded +spec: + serviceAccountName: {{ .Values.operatorServiceAccount }} + containers: + - name: wget + image: "{{ .Values.testFramework.image.repository }}:{{ .Values.testFramework.image.tag }}" + env: + - name: MANAGER_METRICS_SERVICE_CLUSTERIP + value: "appdynamics-cloud-operator-metrics-service" + - name: MANAGER_METRICS_SERVICE_PORT + value: "8443" + command: + - sh + - -c + # The following shell script tests if the appdynamics-cloud-operator-metrics-service is up. + - | + options="--no-check-certificate --server-response --spider --timeout=10" + auth_header="Authorization: Bearer `cat /var/run/secrets/kubernetes.io/serviceaccount/token`" + url="https://$MANAGER_METRICS_SERVICE_CLUSTERIP:$MANAGER_METRICS_SERVICE_PORT/metrics" + + metrics_status=$(wget $options --header="$auth_header" $url 2>&1 | grep "HTTP/" | awk '{print $2}') + if [ "$metrics_status" != "200" ] + then + echo "Metrics check failed" + exit 1 + fi + restartPolicy: Never +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/values.schema.json b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/values.schema.json new file mode 100644 index 00000000..b5eab2d3 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/values.schema.json @@ -0,0 +1,92 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "title": "Values", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "global": { + "type": "object" + }, + "operatorServiceAccount": { + "description": "serviceAccount name for Appdynamics cloud operator", + "type": "string" + }, + "watchMode": { + "description": "changes the scope for certain resources to namespace or cluster scope", + "type": "string", + "enum": ["namespace","cluster"] + }, + "enableOTelCRDManagement": { + "description": "enable OTel CRD management by Appdynamics cloud operator ", + "type": "boolean" + }, + "enableUnifiedOperator": { + "description": "enable cSaaS agent controllers", + "type": "boolean" + }, + "operatorPod": { + "description": "configuration for Appdynamics cloud operator pod", + "type": "object", + "additionalProperties": true, + "properties": { + "image": { + "description": "image URL of Appdynamics cloud operator", + "type": "string" + }, + "imagePullPolicy": { + "description": "image pull policy for Appdynamics cloud operator image", + "type": "string" + } + }, + "required": [ + "image" + ] + }, + "kubeRbacProxy": { + "description": "configuration for kube-rbac-proxy container", + "type": "object", + "additionalProperties": true, + "properties": { + "image": { + "description": "image URL of kube-rbac-proxy", + "type": "string" + }, + "imagePullPolicy": { + "description": "image pull policy for kube-rbac-proxy", + "type": "string" + } + } + }, + "testFramework": { + "description": "test configuration for Appdynamics cloud operator", + "type": "object", + "properties": { + "enabled": { + "description": "enable test for Appdynamics cloud operator", + "type": "boolean" + }, + "image": { + "description": "image information of test container", + "type": "object", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "description": "image repository of test container", + "type": "string" + }, + "tag": { + "description": "image tag of test container", + "type": "string" + } + } + } + } + } + } +} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/values.yaml new file mode 100644 index 00000000..6b9a7eee --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-cloud-operator/values.yaml @@ -0,0 +1,30 @@ +operatorServiceAccount: appdynamics-cloud-operator +enableOTelCRDManagement: true +enableUnifiedOperator: false +watchMode: namespace +operatorPod: + image: appdynamics/appdynamics-cloud-operator:24.4.0-1445 + imagePullPolicy: Always + resources: + limits: + cpu: 200m + memory: 128Mi + requests: + cpu: 100m + memory: 64Mi + labels: {} + annotations: {} + nodeSelector: {} + imagePullSecrets: [] + affinity: {} + tolerations: [] + securityContext: {} + priorityClassName: null +kubeRbacProxy: {} + +testFramework: + # Can be used to disable rendering test resources when using helm template + enabled: true + image: + repository: busybox + tag: latest diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/.helmignore b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/.helmignore new file mode 100644 index 00000000..50d9f6e7 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +build/ \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/Chart.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/Chart.yaml new file mode 100644 index 00000000..ca13c9ce --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/Chart.yaml @@ -0,0 +1,8 @@ +apiVersion: v2 +appVersion: 24.4.73 +description: Helm Charts for installing Appdynamics Smart Agent +home: https://appdynamics.com +icon: https://raw.githubusercontent.com/CiscoDevNet/appdynamics-charts/master/logo.png +name: appdynamics-smartagent +type: application +version: 24.4.73 diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/NOTES.txt b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/NOTES.txt new file mode 100644 index 00000000..bebfa83b --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/NOTES.txt @@ -0,0 +1,30 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +The chart installs the Smart Agent version: {{ .Values.image.tag | default .Chart.AppVersion }}. +This Smart Agent enable managing the Life Cycle of other FSO Agents. + +Smart Agent uses Open Agent Management Protocol (OpAMP) to communicate with the service to enabling +the managing the Life Cycle(LC) of Full Stack Observatory (FSO) agents. + +OpAMP: https://github.com/open-telemetry/opamp-spec/blob/main/specification.md + +Smart Agent is installed with following permissions in the cluster: + + {{- range $role := .Values.clusterRole }} + {{- with $role.apiGroup}} + - apiGroups: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with $role.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with $role.verbs }} + verbs: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/_helpers.tpl b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/_helpers.tpl new file mode 100644 index 00000000..5f424670 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "appdynamics-smartagent.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "appdynamics-smartagent.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "appdynamics-smartagent.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "appdynamics-smartagent.labels" -}} +helm.sh/chart: {{ include "appdynamics-smartagent.chart" . }} +{{ include "appdynamics-smartagent.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "appdynamics-smartagent.selectorLabels" -}} +app.kubernetes.io/name: {{ include "appdynamics-smartagent.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "appdynamics-smartagent.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "appdynamics-smartagent.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/cluster_role.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/cluster_role.yaml new file mode 100644 index 00000000..f58925f6 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/cluster_role.yaml @@ -0,0 +1,21 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "appdynamics-smartagent.fullname" . }} + labels: + {{- include "appdynamics-smartagent.labels" . | nindent 4 }} +rules: + {{- range $role := .Values.clusterRole }} + {{- with $role.apiGroup}} + - apiGroups: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with $role.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with $role.verbs }} + verbs: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/cluster_role_binding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/cluster_role_binding.yaml new file mode 100644 index 00000000..754a5d55 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/cluster_role_binding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "appdynamics-smartagent.fullname" . }} + labels: + {{- include "appdynamics-smartagent.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "appdynamics-smartagent.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "appdynamics-smartagent.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/configmap.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/configmap.yaml new file mode 100644 index 00000000..e8c66dae --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/configmap.yaml @@ -0,0 +1,40 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "appdynamics-smartagent.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "appdynamics-smartagent.labels" . | nindent 4 }} +data: + {{- if contains "localhost" .Values.solution.endpoint }} + SERVICE_URL: {{ .Values.solution.endpoint | required ".Values.solution.endpoint is required for a functional template" }} + {{- else }} + SERVICE_URL: {{ (printf "%s%s" .Values.solution.endpoint .Values.serviceAPIExtension) | required ".Values.solution.endpoint .Values.serviceAPIExtension is required for a functional template" }} + + OAUTH_ID: {{ .Values.oauth.clientId | required ".Values.oauth.clientId is required for a functional template" | quote }} + OAUTH_URL: {{ .Values.oauth.tokenUrl | required ".Values.oauth.tokenUrl is required for a functional template" | quote }} + OAUTH_TENANT_ID: {{ .Values.oauth.tenantId | required ".Values.oauth.tenantId is required for a functional template" | quote }} + OAUTH_SCOPES: {{ .Values.oauth.scopes | quote }} + + INSECURE: {{ default true .Values.tls.insecure | quote }} + CA_FILE: {{ .Values.tls.caFile | quote }} + CERT_FILE: {{ .Values.tls.certFile | quote }} + KEY_FILE: {{ .Values.tls.keyFile | quote }} + + # Go Proxy Configuration https://pkg.go.dev/golang.org/x/net/http/httpproxy + HTTP_PROXY: {{ .Values.proxy.httpProxy | quote }} + HTTPS_PROXY: {{ .Values.proxy.httpsProxy | quote }} + NO_PROXY: {{ .Values.proxy.noProxy | quote }} + {{- end }} + + AGENT_TYPE: {{ .Values.agent.type | required ".Values.agent.type is required for a functional template" }} + AGENT_NAMESPACE: {{ .Values.agent.namespace | required ".Values.agent.namespace is required for a functional template" }} + + AGENT_NAME: {{ .Release.Name | required ".Release.Name is required for a functional template" }} + AGENT_PACKAGE_VERSION: {{ .Values.global.helmChartVersion | required ".Values.global.helmChartVersion is required for a functional template" }} + + K8S_CLUSTER_NAME: {{ .Values.global.clusterName | required ".Values.global.clusterName is required for a functional template"}} + + K8S_DEPLOYMENT_NAME: {{ include "appdynamics-smartagent.fullname" . }} + + IMAGE_REGISTRY: {{ .Values.image.registry | quote }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/deployment.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/deployment.yaml new file mode 100644 index 00000000..6333e474 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/deployment.yaml @@ -0,0 +1,82 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "appdynamics-smartagent.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "appdynamics-smartagent.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "appdynamics-smartagent.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "appdynamics-smartagent.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "appdynamics-smartagent.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: K8S_NAMESPACE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- if (lookup "v1" "Namespace" "" "kube-system").metadata }} + - name: K8S_CLUSTER_ID + value: {{ (lookup "v1" "Namespace" "" "kube-system").metadata.uid | required "Could not fetch kube-system uid to populate clusterID! " }} + {{- else }} + - name: K8S_CLUSTER_ID + value: {{ .Values.global.clusterId | required "clusterId needs to be specified when kube-system metadata is not accessible!" }} + {{- end }} + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- if .Values.oauth.clientSecretEnvVar }} + - name: OAUTH_SECRET + {{- .Values.oauth.clientSecretEnvVar | toYaml | nindent 14}} + {{- end }} + envFrom: + - configMapRef: + name: {{ include "appdynamics-smartagent.fullname" . }} + {{- if .Values.oauth.clientSecret }} + - secretRef: + name: {{ include "appdynamics-smartagent.fullname" . }} + {{- end }} + + resources: + {{- toYaml .Values.resources | nindent 12 }} + terminationGracePeriodSeconds: 30 + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/secret.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/secret.yaml new file mode 100644 index 00000000..19905ebb --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/secret.yaml @@ -0,0 +1,12 @@ +{{- if .Values.oauth.clientSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "appdynamics-smartagent.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "appdynamics-smartagent.labels" . | nindent 4 }} +type: Opaque +stringData: + OAUTH_SECRET: {{ .Values.oauth.clientSecret | required ".Values.oauth.clientSecret is required for a functional template" | quote }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/serviceaccount.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/serviceaccount.yaml new file mode 100644 index 00000000..faa14443 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "appdynamics-smartagent.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "appdynamics-smartagent.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/__snapshot__/deployment_test.yaml.snap b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/__snapshot__/deployment_test.yaml.snap new file mode 100644 index 00000000..94a4ce2e --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/__snapshot__/deployment_test.yaml.snap @@ -0,0 +1,64 @@ +should pass all kinds of assertion: + 1: | + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: fso-agent + app.kubernetes.io/name: appdynamics-smartagent + template: + metadata: + annotations: + checksum/config: 7fb599906d449843d8bac3baa22d3efedac031fdbef3b4741d4540a741808f7b + labels: + app.kubernetes.io/instance: fso-agent + app.kubernetes.io/name: appdynamics-smartagent + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - key: kubernetes.io/os + operator: In + values: + - linux + containers: + - env: + - name: K8S_NAMESPACE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: K8S_CLUSTER_ID + value: clusterID-test + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + envFrom: + - configMapRef: + name: fso-agent-appdynamics-smartagent + - secretRef: + name: fso-agent-appdynamics-smartagent + image: appdynamics/apache:latest + imagePullPolicy: Always + name: appdynamics-smartagent + resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi + securityContext: {} + securityContext: {} + serviceAccountName: fso-agent + terminationGracePeriodSeconds: 30 diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/configmap_test.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/configmap_test.yaml new file mode 100644 index 00000000..d6d24c9f --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/configmap_test.yaml @@ -0,0 +1,43 @@ +suite: test configmap +values: + - ./values/values.yaml +templates: + - configmap.yaml +chart: + version: 0.1.0+test + appVersion: 0.1.0 +release: + name: "fso-agent" + namespace: "appdynamics" +tests: + - it: should pass all kinds of assertion + template: configmap.yaml + documentIndex: 0 + asserts: + - isKind: + of: ConfigMap + - isAPIVersion: + of: v1 + - hasDocuments: + count: 1 + - matchRegex: + path: metadata.name + pattern: ^.*-smartagent$ + - notMatchRegex: + path: metadata.name + pattern: ^.*-foobar$ + - equal: + path: metadata.namespace + value: appdynamics + - notEqual: + path: metadata.namespace + value: default + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: fso-agent + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: appdynamics-smartagent + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: appdynamics-smartagent-0.1.0_test + diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/deployment_test.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/deployment_test.yaml new file mode 100644 index 00000000..b41137f6 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/deployment_test.yaml @@ -0,0 +1,59 @@ +suite: test deployment +values: + - ./values/values.yaml +templates: + - configmap.yaml + - deployment.yaml +chart: + version: 0.1.0+test + appVersion: 0.1.0 +release: + name: "fso-agent" + namespace: "appdynamics" +tests: + - it: should pass all kinds of assertion + template: deployment.yaml + documentIndex: 0 + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: appdynamics/apache:latest + - notEqual: + path: spec.template.spec.containers[0].image + value: nginx:stable + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: fso-agent + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: appdynamics-smartagent + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: appdynamics-smartagent-0.1.0_test + - matchRegex: + path: metadata.name + pattern: ^.*-smartagent$ + - notMatchRegex: + path: metadata.name + pattern: ^.*-foobar$ + - isNull: + path: spec.template.spec.containers[0].ports + - isNull: + path: spec.template.nodeSelector + - isNull: + path: spec.template.spec.containers[1] + - isNotNull: + path: spec.template + - isNotEmpty: + path: spec.template.spec.containers[0] + - isNotEmpty: + path: spec.template.spec.containers[0].resources + - isKind: + of: Deployment + - isAPIVersion: + of: apps/v1 + - hasDocuments: + count: 1 + - matchSnapshot: + path: spec + - isNotNull: + path: spec.template.metadata.annotations \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/role_test.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/role_test.yaml new file mode 100644 index 00000000..6ebe1e00 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/role_test.yaml @@ -0,0 +1,106 @@ +suite: test role +values: + - ./values/values.yaml +templates: + - cluster_role.yaml +chart: + version: 0.1.0+test + appVersion: 0.1.0 +release: + name: "fso-agent" + namespace: "appdynamics" +tests: + - it: should pass all kinds of assertion + template: cluster_role.yaml + documentIndex: 0 + asserts: + - isKind: + of: ClusterRole + - isAPIVersion: + of: rbac.authorization.k8s.io/v1 + - hasDocuments: + count: 1 + - matchRegex: + path: metadata.name + pattern: ^.*-smartagent$ + - notMatchRegex: + path: metadata.name + pattern: ^.*-foobar$ + - isNull: + path: metadata.namespace + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: fso-agent + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: appdynamics-smartagent + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: appdynamics-smartagent-0.1.0_test + - isNotNull: + path: rules + - isNotEmpty: + path: rules[0] + - isNull: + path: rules[4] + - isNotEmpty: + path: rules[0].apiGroups + - isNotEmpty: + path: rules[0].resources + - isNotEmpty: + path: rules[0].verbs + - equal: + path: rules[0].apiGroups + value: + - "" + - equal: + path: rules[1].apiGroups + value: + - rbac.authorization.k8s.io + - equal: + path: rules[2].apiGroups + value: + - rbac.authorization.k8s.io + - equal: + path: rules[0].resources + value: + - configmaps + - secrets + - pods + - pods/logs + - pods/status + - namespaces + - serviceaccounts + - services + - equal: + path: rules[1].resources + value: + - rolebindings + - roles + - equal: + path: rules[2].resources + value: + - roles + - equal: + path: rules[0].verbs + value: + - get + - list + - watch + - update + - create + - delete + - patch + - equal: + path: rules[1].verbs + value: + - get + - list + - watch + - update + - create + - delete + - patch + - equal: + path: rules[2].verbs + value: + - bind \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/rolebinding_test.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/rolebinding_test.yaml new file mode 100644 index 00000000..32d55edc --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/rolebinding_test.yaml @@ -0,0 +1,79 @@ +suite: test rolebinding +values: + - ./values/values.yaml +templates: + - cluster_role_binding.yaml +chart: + version: 0.1.0+test + appVersion: 0.1.0 +release: + name: "fso-agent" + namespace: "appdynamics" +tests: + - it: should pass all kinds of assertion + template: cluster_role_binding.yaml + documentIndex: 0 + asserts: + - isKind: + of: ClusterRoleBinding + - isAPIVersion: + of: rbac.authorization.k8s.io/v1 + - hasDocuments: + count: 1 + - matchRegex: + path: metadata.name + pattern: ^.*-smartagent$ + - notMatchRegex: + path: metadata.name + pattern: ^.*-foobar$ + - isNull: + path: metadata.namespace + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: fso-agent + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: appdynamics-smartagent + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: appdynamics-smartagent-0.1.0_test + - isNotNull: + path: roleRef + - equal: + path: roleRef + value: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: fso-agent-appdynamics-smartagent + - matchRegex: + path: roleRef.name + pattern: ^.*-smartagent$ + - notMatchRegex: + path: roleRef.name + pattern: ^.*-foobar$ + - isNotNull: + path: subjects + - isNotEmpty: + path: subjects[0] + - isNull: + path: subjects[1] + - isNotEmpty: + path: subjects[0].kind + - isNotEmpty: + path: subjects[0].name + - isNotEmpty: + path: subjects[0].namespace + - equal: + path: subjects[0].kind + value: ServiceAccount + - matchRegex: + path: subjects[0].name + pattern: ^.*-agent$ + - notMatchRegex: + path: subjects[0].name + pattern: ^.*-foobar$ + - equal: + path: subjects[0].namespace + value: appdynamics + - notEqual: + path: subjects[0].namespace + value: default \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/secret_test.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/secret_test.yaml new file mode 100644 index 00000000..ed0841db --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/secret_test.yaml @@ -0,0 +1,49 @@ +suite: test secret +values: + - ./values/values.yaml +templates: + - secret.yaml +chart: + version: 0.1.0+test + appVersion: 0.1.0 +release: + name: "fso-agent" + namespace: "appdynamics" +tests: + - it: should pass all kinds of assertion + template: secret.yaml + documentIndex: 0 + asserts: + - isKind: + of: Secret + - isAPIVersion: + of: v1 + - hasDocuments: + count: 1 + - matchRegex: + path: metadata.name + pattern: ^.*-smartagent$ + - notMatchRegex: + path: metadata.name + pattern: ^.*-foobar$ + - equal: + path: metadata.namespace + value: appdynamics + - notEqual: + path: metadata.namespace + value: default + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: fso-agent + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: appdynamics-smartagent + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: appdynamics-smartagent-0.1.0_test + - equal: + path: type + value: Opaque + - equal: + path: stringData + value: + OAUTH_SECRET: "oauthSecret" diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/serviceaccount_test.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/serviceaccount_test.yaml new file mode 100644 index 00000000..e10c3486 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/serviceaccount_test.yaml @@ -0,0 +1,44 @@ +suite: test serviceAccount +values: + - ./values/values.yaml +templates: + - serviceaccount.yaml +chart: + version: 0.1.0+test + appVersion: 0.1.0 +release: + name: "fso-agent" + namespace: "appdynamics" +tests: + - it: should pass all kinds of assertion + template: serviceaccount.yaml + documentIndex: 0 + asserts: + - isKind: + of: ServiceAccount + - isAPIVersion: + of: v1 + - hasDocuments: + count: 1 + - equal: + path: metadata.name + value: fso-agent + - notEqual: + path: metadata.name + pattern: fso-test + - equal: + path: metadata.namespace + value: appdynamics + - notEqual: + path: metadata.namespace + value: default + - equal: + path: metadata.labels + value: + app.kubernetes.io/instance: fso-agent + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: appdynamics-smartagent + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: appdynamics-smartagent-0.1.0_test + - isNull: + path: annotations diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/values/values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/values/values.yaml new file mode 100644 index 00000000..157e399b --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/tests/values/values.yaml @@ -0,0 +1,104 @@ +global: + clusterId: "clusterID-test" + clusterName: "clusterName" + helmChartVersion: "1.21.0" + +image: + registry: appdynamics + repository: apache + tag: latest + pullPolicy: Always + +namespace: appdynamics + +clusterRole: + - apiGroup: [ "" ] + resources: [ + configmaps, + secrets, + pods, + pods/logs, + pods/status, + namespaces, + serviceaccounts, + services, + ] + verbs: [ + get, + list, + watch, + update, + create, + delete, + patch, + ] + - apiGroup: [ rbac.authorization.k8s.io ] + resources: [ + rolebindings, + roles, + ] + verbs: [ + get, + list, + watch, + update, + create, + delete, + patch, + ] + - apiGroup: [ rbac.authorization.k8s.io ] + resources: [ + roles, + ] + verbs: [ + bind, + ] + resourceNames: [ + admin, + edit, + view, + ] + - apiGroup: [ + apps, + extensions, + ] + resources: [ + daemonsets, + daemonsets/status, + deployments, + deployments/status, + replicasets, + statefulsets, + statefulsets/status, + ] + verbs: [ + get, + list, + watch, + update, + create, + delete, + patch, + ] + +serviceAccount: + create: true + annotations: {} + name: "fso-agent" + +solution: + endpoint: "solutionURL" + +oauth: + clientId: "oauthId" + clientSecret: "oauthSecret" + tokenUrl: "oauthURL" + tenantId: "tenantID" + scopes: "a,b,c" + +tls: + insecure: true + +agent: + name: "smartagent" + namespace: "agent" diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/values.yaml new file mode 100644 index 00000000..0d98c253 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/appdynamics-smartagent/values.yaml @@ -0,0 +1,237 @@ +# Default values for appdynamics-smartagent. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +global: + clusterId: "" + clusterName: "appdynamics" + helmChartVersion: "latest" + +image: + registry: appdynamics + repository: appdynamics-smartagent + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "24.4.0-1960" + +serviceAPIExtension: "/rest/agent/service" + +clusterRole: + - apiGroup: [ "" ] + resources: [ + configmaps, + secrets, + pods, + pods/logs, + pods/status, + namespaces, + serviceaccounts, + services, + endpoints, + events, + nodes, + nodes/proxy, + resourcequotas, + persistentvolumeclaims, + persistentvolumes, + replicationcontrollers, + ] + verbs: [ + get, + list, + watch, + update, + create, + delete, + patch, + ] + - apiGroup: [ rbac.authorization.k8s.io ] + resources: [ + clusterrolebindings, + clusterroles, + rolebindings, + roles, + ] + verbs: [ + get, + list, + watch, + update, + create, + delete, + patch, + ] + - apiGroup: [ rbac.authorization.k8s.io ] + resources: [ + roles, + ] + verbs: [ + bind, + ] + resourceNames: [ + admin, + edit, + view, + ] + - apiGroup: [ + apps, + extensions, + ] + resources: [ + daemonsets, + daemonsets/status, + deployments, + deployments/status, + replicasets, + statefulsets, + statefulsets/status, + ] + verbs: [ + get, + list, + watch, + update, + create, + delete, + patch, + ] + - apiGroup: [ networking.k8s.io ] + resources: [ + ingresses, + ] + verbs: [ + get, + list, + watch, + ] + - apiGroup: [ autoscaling.k8s.io ] + resources: [ + verticalpodautoscalers, + ] + verbs: [ + get, + list, + watch, + ] + - apiGroup: [ autoscaling ] + resources: [ + horizontalpodautoscalers, + ] + verbs: [ + get, + list, + watch, + ] + - apiGroup: [ batch ] + resources: [ + cronjobs, + jobs, + ] + verbs: [ + get, + list, + watch, + ] + - apiGroup: [ cluster.appdynamics.com ] + resources: [ + clustermons, + containermons, + inframons, + logcollectors, + servermons, + ] + verbs: [ + get, + list, + watch, + update, + create, + delete, + patch, + ] + - apiGroup: [ opentelemetry.io ] + resources: [ + instrumentations, + opentelemetrycollectors, + ] + verbs: [ + get, + list, + watch, + update, + create, + delete, + patch, + ] + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "appd-smartagent" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + +resources: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - key: kubernetes.io/os + operator: In + values: + - linux + +solution: + endpoint: "" + +oauth: + clientId: "" + clientSecret: "" + tokenUrl: "" + tenantId: "" + scopes: "" + clientSecretEnvVar: {} + +tls: + insecure: true + caFile: "" + certFile: "" + keyFile: "" + +agent: + type: "smartagent" + namespace: "agent" + +proxy: + httpProxy: "" + httpsProxy: "" + noProxy: "" diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/.helmignore b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/.helmignore new file mode 100644 index 00000000..7e96254a --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/.helmignore @@ -0,0 +1,25 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +# Release related files +release/ diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/CONTRIBUTING.md b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/CONTRIBUTING.md new file mode 100644 index 00000000..b84ea2a3 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Operator Chart Contributing Guide + +## Bumping Default Operator Version + +1. Increase the minor version of the chart by one and set the patch version to zero. +2. Update the chart's `appVersion` to match the new operator version. +3. In the values.yaml, update `manager.image.tag` to match the new operator release. +4. In the values.yaml, update `manager.collectorImage.tag` to match the version of the collector managed by default by the operator. +5. Run `make generate-examples CHARTS=opentelemetry-operator`. +6. Run `make update-operator-crds` to update the CRDs in this chart to match the operator's. +7. Review the [Operator release notes](https://github.com/open-telemetry/opentelemetry-operator/releases). If any changes affect the helm chart, adjust the helm chart accordingly. diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/Chart.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/Chart.yaml new file mode 100644 index 00000000..f9a0c1e0 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v2 +appVersion: 0.89.0 +description: AppDynamics Distribution of OpenTelemetry Operator Helm chart for Kubernetes +home: https://appdynamics.com +icon: https://raw.githubusercontent.com/CiscoDevNet/appdynamics-charts/master/logo.png +maintainers: +- email: support@appdynamics.com + name: AppDynamics +name: opentelemetry-operator +sources: +- https://github.com/open-telemetry/opentelemetry-operator +type: application +version: 0.43.0 diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/LICENSE.txt b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/LICENSE.txt new file mode 100644 index 00000000..f49a4e16 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/README.md b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/README.md new file mode 100644 index 00000000..f08c839c --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/README.md @@ -0,0 +1,273 @@ +# OpenTelemetry Operator Helm Chart + +The Helm chart installs [OpenTelemetry Operator](https://github.com/open-telemetry/opentelemetry-operator) in Kubernetes cluster. +The OpenTelemetry Operator is an implementation of a [Kubernetes Operator](https://www.openshift.com/learn/topics/operators). +At this point, it has [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector) as the only managed component. + +## Prerequisites + +- Kubernetes 1.24+ is required for OpenTelemetry Operator installation +- Helm 3.9+ + +### TLS Certificate Requirement + +In Kubernetes, in order for the API server to communicate with the webhook component, the webhook requires a TLS +certificate that the API server is configured to trust. There are a few different ways you can use to generate/configure the required TLS certificate. + + - The easiest and default method is to install the [cert-manager](https://cert-manager.io/docs/) and set `admissionWebhooks.certManager.create` to `true`. + In this way, cert-manager will generate a self-signed certificate. _See [cert-manager installation](https://cert-manager.io/docs/installation/kubernetes/) for more details._ + - You can provide your own Issuer by configuring the `admissionWebhooks.certManager.issuerRef` value. You will need + to specify the `kind` (Issuer or ClusterIssuer) and the `name`. Note that this method also requires the installation of cert-manager. + - You can use an automatically generated self-signed certificate by setting `admissionWebhooks.certManager.enabled` to `false` and `admissionWebhooks.autoGenerateCert` to `true`. Helm will create a self-signed cert and a secret for you. + - You can use your own generated self-signed certificate by setting both `admissionWebhooks.certManager.enabled` and `admissionWebhooks.autoGenerateCert` to `false`. You should provide the necessary values to `admissionWebhooks.cert_file`, `admissionWebhooks.key_file`, and `admissionWebhooks.ca_file`. + - You can sideload custom webhooks and certificate by disabling `.Values.admissionWebhooks.create` and `admissionWebhooks.certManager.enabled` while setting your custom cert secret name in `admissionWebhooks.secretName` + - You can disable webhooks altogether by disabling `.Values.admissionWebhooks.create` and setting env var to `ENABLE_WEBHOOKS: "false"` + +## Add Repository + +```console +$ helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts +$ helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + +## Install Chart + +```console +$ helm install \ + opentelemetry-operator open-telemetry/opentelemetry-operator +``` + +If you created a custom namespace, like in the TLS Certificate Requirement section above, you will need to specify the namespace with the `--namespace` helm option: + +```console +$ helm install --namespace opentelemetry-operator-system \ + opentelemetry-operator open-telemetry/opentelemetry-operator +``` + +If you wish for helm to create an automatically generated self-signed certificate, make sure to set the appropriate values when installing the chart: + +```console +$ helm install --set admissionWebhooks.certManager.enabled=false --set admissionWebhooks.certManager.autoGenerateCert=true \ + opentelemetry-operator open-telemetry/opentelemetry-operator +``` + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +## Uninstall Chart + +The following command uninstalls the chart whose release name is my-opentelemetry-operator. + +```console +$ helm uninstall opentelemetry-operator +``` + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +This will remove all the Kubernetes components associated with the chart and deletes the release. + +The OpenTelemetry Collector CRD created by this chart won't be removed by default and should be manually deleted: + +```console +$ kubectl delete crd opentelemetrycollectors.opentelemetry.io +``` + +## Upgrade Chart + +```console +$ helm upgrade my-opentelemetry-operator open-telemetry/opentelemetry-operator +``` + +Please note that by default, the chart will be upgraded to the latest version. If you want to upgrade to a specific version, +use `--version` flag. + +With Helm v3.0, CRDs created by this chart are not updated by default and should be manually updated. +Consult also the [Helm Documentation on CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions). + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +## Configuration + +The following command will show all the configurable options with detailed comments. + +```console +$ helm show values open-telemetry/opentelemetry-operator +``` + +## Install OpenTelemetry Collector + +_See [OpenTelemetry website](https://opentelemetry.io/docs/collector/) for more details about the Collector_ + +Once the opentelemetry-operator deployment is ready, you can deploy OpenTelemetry Collector in our Kubernetes +cluster. + +The Collector can be deployed as one of four modes: Deployment, DaemonSet, StatefulSet and Sidecar. The default +mode is Deployment. We will introduce the benefits and use cases of each mode as well as giving an example for each. + +### Deployment Mode + +If you want to get more control of the OpenTelemetry Collector and create a standalone application, Deployment would +be your choice. With Deployment, you can relatively easily scale up the Collector to monitor more targets, roll back +to an early version if anything unexpected happens, pause the Collector, etc. In general, you can manage your Collector +instance just as an application. + +The following example configuration deploys the Collector as Deployment resource. The receiver is Jaeger receiver and +the exporter is [debug exporter](https://github.com/open-telemetry/opentelemetry-collector/blob/main/exporter/debugexporter). + +```console +$ kubectl apply -f - < +It is important that the `jaegerremotesampling` extension and the `jaegerreceiver` do not use the same port.
To increase the collector version afterwards, the update must be triggered again by restarting the operator. Alternatively, the `OpenTelemetryCollector` CRD can be re-created. [otel-contrib#14707](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/14707) + +## 0.13.0 to 0.14.0 + +[Allow byo webhooks and cert](https://github.com/open-telemetry/opentelemetry-helm-charts/pull/411) + +The ability to use admission webhooks has been moved from `admissionWebhooks.enabled` to `admissionWebhooks.create` as it now supports more use cases. + +In order to completely disable admission webhooks you need to explicitly set the environment variable `ENABLE_WEBHOOKS: "false"` in `.Values.manager.env` . diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/cert-manager-disable-nameoverride-values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/cert-manager-disable-nameoverride-values.yaml new file mode 100644 index 00000000..63c2261f --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/cert-manager-disable-nameoverride-values.yaml @@ -0,0 +1,5 @@ +nameOverride: no-cert-manager + +admissionWebhooks: + certManager: + enabled: false diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/cert-manager-disable-values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/cert-manager-disable-values.yaml new file mode 100644 index 00000000..0a32bfec --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/cert-manager-disable-values.yaml @@ -0,0 +1,3 @@ +admissionWebhooks: + certManager: + enabled: false diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/nameoverride-values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/nameoverride-values.yaml new file mode 100644 index 00000000..0a6e63a7 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/nameoverride-values.yaml @@ -0,0 +1 @@ +nameOverride: foobar diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/secret-name-nameoverride-values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/secret-name-nameoverride-values.yaml new file mode 100644 index 00000000..4007e428 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/secret-name-nameoverride-values.yaml @@ -0,0 +1,4 @@ +nameOverride: secret-name + +admissionWebhooks: + secretName: random-name diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/secret-name-values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/secret-name-values.yaml new file mode 100644 index 00000000..f18d281e --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/ci/secret-name-values.yaml @@ -0,0 +1,2 @@ +admissionWebhooks: + secretName: random-name diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetry.io_opampbridges.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetry.io_opampbridges.yaml new file mode 100644 index 00000000..913746b3 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetry.io_opampbridges.yaml @@ -0,0 +1,2823 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + name: opampbridges.opentelemetry.io +spec: + group: opentelemetry.io + names: + kind: OpAMPBridge + listKind: OpAMPBridgeList + plural: opampbridges + singular: opampbridge + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: OpenTelemetry Version + jsonPath: .status.version + name: Version + type: string + - jsonPath: .spec.endpoint + name: Endpoint + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: OpAMPBridge is the Schema for the opampbridges API. + properties: + apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. + type: string + kind: + description: Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. + type: string + metadata: + type: object + spec: + description: OpAMPBridgeSpec defines the desired state of OpAMPBridge. + properties: + affinity: + description: If specified, indicates the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose ' + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-locate + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose ' + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose ' + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-locate + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose ' + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + capabilities: + additionalProperties: + type: boolean + description: Capabilities supported by the OpAMP Bridge + type: object + componentsAllowed: + additionalProperties: + items: + type: string + type: array + description: ComponentsAllowed is a list of allowed OpenTelemetry + components for each pipeline type (receiver, processor, etc.) + type: object + endpoint: + description: OpAMP backend Server endpoint + type: string + env: + description: ENV vars to set on the OpAMPBridge Pods. + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: List of sources to populate environment variables on + the OpAMPBridge Pods. + items: + description: EnvFromSource represents the source of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to each key in + the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + hostNetwork: + description: HostNetwork indicates if the pod should run in the host + networking namespace. + type: boolean + image: + description: Image indicates the container image to use for the OpAMPBridge. + type: string + imagePullPolicy: + description: ImagePullPolicy indicates the pull policy to be used + for retrieving the container image (Always, Never, IfNotPresent) + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector to schedule OpAMPBridge pods. + type: object + podAnnotations: + additionalProperties: + type: string + description: PodAnnotations is the set of annotations that will be + attached to OpAMPBridge pods. + type: object + podSecurityContext: + description: PodSecurityContext will be set as the pod security context. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1." + format: int64 + type: integer + fsGroupChangePolicy: + description: fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for th + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + type: string + type: object + type: object + ports: + description: Ports allows a set of ports to be exposed by the underlying + v1.Service. + items: + description: ServicePort contains information on service's port. + properties: + appProtocol: + description: The application protocol for this port. This is + used as a hint for implementations to offer richer behavior + for protocols that they understand. This field follows standard + Kubernetes label syntax. + type: string + name: + description: The name of this port within the service. This + must be a DNS_LABEL. All ports within a ServiceSpec must have + unique names. + type: string + nodePort: + description: The port on each node on which this service is + exposed when type is NodePort or LoadBalancer. Usually assigned + by the system. + format: int32 + type: integer + port: + description: The port that will be exposed by this service. + format: int32 + type: integer + protocol: + default: TCP + description: The IP protocol for this port. Supports "TCP", + "UDP", and "SCTP". Default is TCP. + type: string + targetPort: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the pods + targeted by the service. Number must be in the range 1 to + 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: array + x-kubernetes-list-type: atomic + priorityClassName: + description: If specified, indicates the pod's priority. If not specified, + the pod priority will be default or zero if there is no default. + type: string + replicas: + description: Replicas is the number of pod instances for the OpAMPBridge. + format: int32 + maximum: 1 + type: integer + resources: + description: Resources to set on the OpAMPBridge pods. + properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims + of the Pod where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources + allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + securityContext: + description: SecurityContext will be set as the container security + context. + properties: + allowPrivilegeEscalation: + description: AllowPrivilegeEscalation controls whether a process + can gain more privileges than its parent process. This bool + directly controls if the no_new_privs flag will be set on the + container process. + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container + runtime. Note that this field cannot be set when spec.os.name + is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in privileged + containers are essentially equivalent to root on the host. Defaults + to false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use for + the containers. The default is DefaultProcMount which uses the + container runtime defaults for readonly paths and masked paths. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in PodSecurityContext. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in PodSecurityContext. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. If + seccomp options are provided at both the pod & container level, + the container options override the pod options. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will + be used. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + type: string + type: object + type: object + serviceAccount: + description: ServiceAccount indicates the name of an existing service + account to use with this instance. When set, the operator will not + automatically create a ServiceAccount for the OpAMPBridge. + type: string + tolerations: + description: Toleration to schedule OpAMPBridge pods. + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: TopologySpreadConstraints embedded kubernetes pod configuration + option, controls how pods are spread across your cluster among failure-domains + such as regions, zones, nodes, and other user-defined top + items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching pods. Pods + that match this label selector are counted to determine the + number of pods in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists or + DoesNotExist, the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys to select + the pods over which spreading will be calculated. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: MaxSkew describes the degree to which pods may + be unevenly distributed. + format: int32 + type: integer + minDomains: + description: MinDomains indicates a minimum number of eligible + domains. + format: int32 + type: integer + nodeAffinityPolicy: + description: NodeAffinityPolicy indicates how we will treat + Pod's nodeAffinity/nodeSelector when calculating pod topology + spread skew. + type: string + nodeTaintsPolicy: + description: NodeTaintsPolicy indicates how we will treat node + taints when calculating pod topology spread skew. + type: string + topologyKey: + description: TopologyKey is the key of node labels. Nodes that + have a label with this key and identical values are considered + to be in the same topology. + type: string + whenUnsatisfiable: + description: WhenUnsatisfiable indicates how to deal with a + pod if it doesn't satisfy the spread constraint. - DoNotSchedule + (default) tells the scheduler not to schedule it. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + upgradeStrategy: + description: UpgradeStrategy represents how the operator will handle + upgrades to the CR when a newer version of the operator is deployed + enum: + - automatic + - none + type: string + volumeMounts: + description: VolumeMounts represents the mount points to use in the + underlying OpAMPBridge deployment(s) + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume should + be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are propagated + from the host to container and the other way around. When + not set, MountPropagationNone is used. This field is beta + in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which the + container's volume should be mounted. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-type: atomic + volumes: + description: Volumes represents which volumes to use in the underlying + OpAMPBridge deployment(s). + items: + description: Volume represents a named volume in a pod that may + be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs".' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount + by volume name. Examples: For volume /dev/sda1, you specify + the partition as "1".' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent disk + resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount on + the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: None, + Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in the + blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the blob + storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must be + a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single blob + disk per storage account Managed: azure managed data + disk (only in managed availability set).' + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service mount + on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host that + shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is the + path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is empty. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is optional: User is the rados user name, + default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached and + mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred to + be "ext4" if unspecified.' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + description: 'volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should populate + this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used to + set permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value between + 0 and 511.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair in + the Data field of the referenced ConfigMap will be projected + into the volume as a file whose name is the key and content + is the value. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents ephemeral + storage that is handled by certain external CSI drivers (Beta + feature). + properties: + driver: + description: driver is the name of the CSI driver that handles + this volume. Consult with your admin for the correct name + as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the associated + CSI driver which will determine the default filesystem + to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to the + secret object containing sensitive information to pass + to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific properties + that are passed to the CSI driver. Consult your driver's + documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the pod + that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created files + by default. Must be a Optional: mode bits used to set + permissions on created files by default.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the pod: + only annotations, labels, name and namespace are + supported.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + description: 'Optional: mode bits used to set permissions + on this file, must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative path + name of the file to be created. Must not be absolute + or contain the ''..'' path. Must be utf-8 encoded. + The first item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory that + shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: medium represents what type of storage medium + should back this directory. The default is "" which means + to use the node's default medium. Must be an empty string + (default) or Memory. + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is also + applicable for memory medium. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: ephemeral represents a volume that is handled by + a cluster storage driver. + properties: + volumeClaimTemplate: + description: Will be used to create a stand-alone PVC to + provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. + properties: + metadata: + description: May contain labels and annotations that + will be copied into the PVC when creating it. No other + fields are allowed and will be rejected during validation. + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the PVC + that gets created from this template. + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API + group. For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: dataSourceRef specifies the object + from which to populate the volume with data, if + a non-empty volume is desired. + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API + group. For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace + is specified, a gateway.networking.k8s. + type: string + required: + - kind + - name + type: object + resources: + description: resources represents the minimum resources + the volume should have. + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used + by this container. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name + of one entry in pod.spec.resourceClaims + of the Pod where this field is used. + It makes that resource available inside + a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum + amount of compute resources required. + type: object + type: object + selector: + description: selector is a label query over volumes + to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: 'storageClassName is the name of the + StorageClass required by the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem + is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that is + attached to a kubelet's host machine and then exposed to the + pod. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs and + lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use for + this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". The default filesystem depends + on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds extra + command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if no + secret object is specified.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached to + a kubelet's host machine. This depends on the Flocker control + service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored as + metadata -> name on the dataset for Flocker should be + considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. This + is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.' + properties: + fsType: + description: 'fsType is filesystem type of the volume that + you want to mount. Tip: Ensure that the filesystem type + is supported by the host operating system. Examples: "ext4", + "xfs", "ntfs".' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount + by volume name. Examples: For volume /dev/sda1, you specify + the partition as "1".' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource in + GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated.' + properties: + directory: + description: directory is the target directory name. Must + not contain or start with '..'. If '.' is supplied, the + volume directory will be the git repository. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More info: + https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs volume + to be mounted with read-only permissions. Defaults to + false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: hostPath represents a pre-existing file or directory + on the host machine that is directly exposed to the container. + properties: + path: + description: 'path of the directory on the host. If the + path is a symlink, it will follow the link to the real + path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that is + attached to a kubelet''s host machine and then exposed to + the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support iSCSI + Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support iSCSI + Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs".' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that uses + an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. The + portal is either an IP or ip_addr:port if the port is + other than default (typically TCP ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI target + and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. The Portal + is either an IP or ip_addr:port if the port is other than + default (typically TCP ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL and unique + within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host that shares + a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. More + info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export to + be mounted with read-only permissions. Defaults to false. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of the + NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents a + reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting in + VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set permissions + on created files by default. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along with + other supported volume types + properties: + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be + an octal value between 0000 and 0777 or + a decimal value between 0 and 511.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' + path. Must be utf-8 encoded. The first + item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and requests + (limits.cpu, limits.memory, requests.cpu + and requests.memory) are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret data + to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional field specify whether the + Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information about + the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must identify + itself with an identifier specified in the audience + of the token, and otherwise should reject the + token. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, the + kubelet volume plugin will proactively rotate + the service account token. + format: int64 + type: integer + path: + description: path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is no + group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults to + false. + type: boolean + registry: + description: registry represents a single or multiple Quobyte + Registry services specified as a string as host:port pair + (multiple entries are separated with commas) which acts + as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume in the + Backend Used with dynamically provisioned Quobyte volumes, + value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to serivceaccount + user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs".' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication secret + for RBDUser. If provided overrides keyring. Default is + nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is the rados user name. Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for ScaleIO + user and other sensitive information. If this is not provided, + Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage for + a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: system is the name of the storage system as + configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to + set permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value between + 0 and 511.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for obtaining + the StorageOS API credentials. If not specified, default + values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + description: volumeName is the human-readable name of the + StorageOS volume. Volume names are only unique within + a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of the + volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must be + a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy Based + Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies vSphere + volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-type: atomic + required: + - capabilities + - endpoint + type: object + status: + description: OpAMPBridgeStatus defines the observed state of OpAMPBridge. + properties: + version: + description: Version of the managed OpAMP Bridge (operand) + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetrycollector.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetrycollector.yaml new file mode 100644 index 00000000..de4a4780 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetrycollector.yaml @@ -0,0 +1,7092 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + name: opentelemetrycollectors.opentelemetry.io +spec: + group: opentelemetry.io + names: + kind: OpenTelemetryCollector + listKind: OpenTelemetryCollectorList + plural: opentelemetrycollectors + shortNames: + - otelcol + - otelcols + singular: opentelemetrycollector + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Deployment Mode + jsonPath: .spec.mode + name: Mode + type: string + - description: OpenTelemetry Version + jsonPath: .status.version + name: Version + type: string + - jsonPath: .status.scale.statusReplicas + name: Ready + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.image + name: Image + type: string + - description: Management State + jsonPath: .spec.managementState + name: Management + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: OpenTelemetryCollector is the Schema for the opentelemetrycollectors + API. + properties: + apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. + type: string + kind: + description: Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. + type: string + metadata: + type: object + spec: + description: OpenTelemetryCollectorSpec defines the desired state of OpenTelemetryCollector. + properties: + additionalContainers: + description: AdditionalContainers allows injecting additional containers + into the Collector's pod definition. + items: + description: A single application container that you want to run + within a pod. + properties: + args: + description: Arguments to the entrypoint. The container image's + CMD is used if this is not provided. Variable references $(VAR_NAME) + are expanded using the container's environment. + items: + type: string + type: array + command: + description: Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's + environment. + items: + type: string + type: array + env: + description: List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: List of sources to populate environment variables + in the container. The keys defined within a source must be + a C_IDENTIFIER. + items: + description: EnvFromSource represents the source of a set + of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to each + key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent + otherwise. Cannot be updated. More info: https://kubernetes.' + type: string + lifecycle: + description: Actions that the management system should take + in response to container lifecycle events. Cannot be updated. + properties: + postStart: + description: PostStart is called immediately after a container + is created. If the handler fails, the container is terminated + and restarted according to its restart policy. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward compatibility. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: PreStop is called immediately before a container + is terminated due to an API request or management event + such as liveness/startup probe failure, preemption, resource + contention, etc. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward compatibility. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. Container + will be restarted if the probe fails. Cannot be updated. More + info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for the + command is root ('/') in the container's filesystem. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. Not + specifying a port here DOES NOT prevent that port from being + exposed. Any port which is listening on the default "0.0.0. + items: + description: ContainerPort represents a network port in a + single container. + properties: + containerPort: + description: Number of port to expose on the pod's IP + address. This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: Number of port to expose on the host. If + specified, this must be a valid port number, 0 < x < + 65536. If HostNetwork is specified, this must match + ContainerPort. Most containers do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a pod + must have a unique name. Name for the port that can + be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe + fails. Cannot be updated. More info: https://kubernetes.' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for the + command is root ('/') in the container's filesystem. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource resize + policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this resource + resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource + is resized. If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + restartPolicy: + description: RestartPolicy defines the restart behavior of individual + containers in a pod. This field may only be set for init containers, + and the only allowed value is "Always". + type: string + securityContext: + description: SecurityContext defines the security options the + container should be run with. If set, the fields of SecurityContext + override the equivalent fields of PodSecurityContext. + properties: + allowPrivilegeEscalation: + description: AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. + type: string + type: object + type: object + startupProbe: + description: StartupProbe indicates that the Pod has successfully + initialized. If specified, no other probes are executed until + this completes successfully. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for the + command is root ('/') in the container's filesystem. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate a buffer + for stdin in the container runtime. If this is not set, reads + from stdin in the container will always result in EOF. Default + is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close the + stdin channel after it has been opened by a single attach. + When stdin is true the stdin stream will remain open across + multiple attach sessions. + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which the + container''s termination message will be written is mounted + into the container''s filesystem.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should be + populated. File will use the contents of terminationMessagePath + to populate the container status message on both success and + failure. + type: string + tty: + description: Whether this container should allocate a TTY for + itself, also requires 'stdin' to be true. Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices to be + used by the container. + items: + description: volumeDevice describes a mapping of a raw block + device within a container. + properties: + devicePath: + description: devicePath is the path inside of the container + that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other + way around. When not set, MountPropagationNone is used. + This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which might + be configured in the container image. Cannot be updated. + type: string + required: + - name + type: object + type: array + affinity: + description: If specified, indicates the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose ' + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-locate + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose ' + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose ' + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-locate + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose ' + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + args: + additionalProperties: + type: string + description: Args is the set of arguments to pass to the OpenTelemetry + Collector binary + type: object + autoscaler: + description: Autoscaler specifies the pod autoscaling configuration + to use for the OpenTelemetryCollector workload. + properties: + behavior: + description: HorizontalPodAutoscalerBehavior configures the scaling + behavior of the target in both Up and Down directions (scaleUp + and scaleDown fields respectively). + properties: + scaleDown: + description: scaleDown is scaling policy for scaling Down. + If not set, the default value is to allow to scale down + to minReplicas pods, with a 300 second stabilization window + (i.e. + properties: + policies: + description: policies is a list of potential scaling polices + which can be used during scaling. At least one policy + must be specified, otherwise the HPAScalingRules will + be discarded as invalid + items: + description: HPAScalingPolicy is a single policy which + must hold true for a specified past interval. + properties: + periodSeconds: + description: periodSeconds specifies the window + of time for which the policy should hold true. + PeriodSeconds must be greater than zero and less + than or equal to 1800 (30 min). + format: int32 + type: integer + type: + description: type is used to specify the scaling + policy. + type: string + value: + description: value contains the amount of change + which is permitted by the policy. It must be greater + than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: selectPolicy is used to specify which policy + should be used. If not set, the default value Max is + used. + type: string + stabilizationWindowSeconds: + description: stabilizationWindowSeconds is the number + of seconds for which past recommendations should be + considered while scaling up or scaling down. + format: int32 + type: integer + type: object + scaleUp: + description: scaleUp is scaling policy for scaling Up. + properties: + policies: + description: policies is a list of potential scaling polices + which can be used during scaling. At least one policy + must be specified, otherwise the HPAScalingRules will + be discarded as invalid + items: + description: HPAScalingPolicy is a single policy which + must hold true for a specified past interval. + properties: + periodSeconds: + description: periodSeconds specifies the window + of time for which the policy should hold true. + PeriodSeconds must be greater than zero and less + than or equal to 1800 (30 min). + format: int32 + type: integer + type: + description: type is used to specify the scaling + policy. + type: string + value: + description: value contains the amount of change + which is permitted by the policy. It must be greater + than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: selectPolicy is used to specify which policy + should be used. If not set, the default value Max is + used. + type: string + stabilizationWindowSeconds: + description: stabilizationWindowSeconds is the number + of seconds for which past recommendations should be + considered while scaling up or scaling down. + format: int32 + type: integer + type: object + type: object + maxReplicas: + description: MaxReplicas sets an upper bound to the autoscaling + feature. If MaxReplicas is set autoscaling is enabled. + format: int32 + type: integer + metrics: + description: Metrics is meant to provide a customizable way to + configure HPA metrics. currently the only supported custom metrics + is type=Pod. + items: + description: MetricSpec defines a subset of metrics to be defined + for the HPA's metric array more metric type can be supported + as needed. See https://pkg.go.dev/k8s.io/api/autoscaling/v2#MetricSpec + for reference. + properties: + pods: + description: PodsMetricSource indicates how to scale on + a metric describing each pod in the current scale target + (for example, transactions-processed-per-second). + properties: + metric: + description: metric identifies the target metric by + name and selector + properties: + name: + description: name is the name of the given metric + type: string + selector: + description: selector is the string-encoded form + of a standard kubernetes label selector for the + given metric When set, it is passed as an additional + parameter to the metrics server for more specific + metrics scopi + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target value for the + given metric + properties: + averageUtilization: + description: averageUtilization is the target value + of the average of the resource metric across all + relevant pods, represented as a percentage of + the requested value of the resource for the pods. + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: averageValue is the target value of + the average of the metric across all relevant + pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the metric + type is Utilization, Value, or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of the metric + (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + type: + description: MetricSourceType indicates the type of metric. + type: string + required: + - type + type: object + type: array + minReplicas: + description: MinReplicas sets a lower bound to the autoscaling + feature. Set this if your are using autoscaling. It must be + at least 1 + format: int32 + type: integer + targetCPUUtilization: + description: TargetCPUUtilization sets the target average CPU + used across all replicas. If average CPU exceeds this value, + the HPA will scale up. Defaults to 90 percent. + format: int32 + type: integer + targetMemoryUtilization: + description: TargetMemoryUtilization sets the target average memory + utilization across all replicas + format: int32 + type: integer + type: object + config: + description: Config is the raw JSON to be used as the collector's + configuration. Refer to the OpenTelemetry Collector documentation + for details. + type: string + configmaps: + description: ConfigMaps is a list of ConfigMaps in the same namespace + as the OpenTelemetryCollector object, which shall be mounted into + the Collector Pods. + items: + properties: + mountpath: + type: string + name: + description: Configmap defines name and path where the configMaps + should be mounted. + type: string + required: + - mountpath + - name + type: object + type: array + env: + description: ENV vars to set on the OpenTelemetry Collector's Pods. + These can then in certain cases be consumed in the config file for + the Collector. + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: List of sources to populate environment variables on + the OpenTelemetry Collector's Pods. These can then in certain cases + be consumed in the config file for the Collector. + items: + description: EnvFromSource represents the source of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to each key in + the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + hostNetwork: + description: HostNetwork indicates if the pod should run in the host + networking namespace. + type: boolean + image: + description: Image indicates the container image to use for the OpenTelemetry + Collector. + type: string + imagePullPolicy: + description: ImagePullPolicy indicates the pull policy to be used + for retrieving the container image (Always, Never, IfNotPresent) + type: string + ingress: + description: 'Ingress is used to specify how OpenTelemetry Collector + is exposed. This functionality is only available if one of the valid + modes is set. Valid modes are: deployment, daemonset and statefulset.' + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations to add to ingress. e.g. ''cert-manager.io/cluster-issuer: + "letsencrypt"''' + type: object + hostname: + description: Hostname by which the ingress proxy can be reached. + type: string + ingressClassName: + description: IngressClassName is the name of an IngressClass cluster + resource. Ingress controller implementations use this field + to know whether they should be serving this Ingress resource. + type: string + route: + description: Route is an OpenShift specific section that is only + considered when type "route" is used. + properties: + termination: + description: Termination indicates termination type. By default + "edge" is used. + enum: + - insecure + - edge + - passthrough + - reencrypt + type: string + type: object + ruleType: + description: RuleType defines how Ingress exposes collector receivers. + IngressRuleTypePath ("path") exposes each receiver port on a + unique path on single domain defined in Hostname. + enum: + - path + - subdomain + type: string + tls: + description: TLS configuration. + items: + description: IngressTLS describes the transport layer security + associated with an ingress. + properties: + hosts: + description: hosts is a list of hosts included in the TLS + certificate. The values in this list must match the name/s + used in the tlsSecret. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: secretName is the name of the secret used to + terminate TLS traffic on port 443. Field is left optional + to allow TLS routing based on SNI hostname alone. + type: string + type: object + type: array + type: + description: 'Type default value is: "" Supported types are: ingress, + route' + enum: + - ingress + - route + type: string + type: object + initContainers: + description: InitContainers allows injecting initContainers to the + Collector's pod definition. + items: + description: A single application container that you want to run + within a pod. + properties: + args: + description: Arguments to the entrypoint. The container image's + CMD is used if this is not provided. Variable references $(VAR_NAME) + are expanded using the container's environment. + items: + type: string + type: array + command: + description: Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's + environment. + items: + type: string + type: array + env: + description: List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: List of sources to populate environment variables + in the container. The keys defined within a source must be + a C_IDENTIFIER. + items: + description: EnvFromSource represents the source of a set + of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to each + key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: 'Container image name. More info: https://kubernetes.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent + otherwise. Cannot be updated. More info: https://kubernetes.' + type: string + lifecycle: + description: Actions that the management system should take + in response to container lifecycle events. Cannot be updated. + properties: + postStart: + description: PostStart is called immediately after a container + is created. If the handler fails, the container is terminated + and restarted according to its restart policy. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward compatibility. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: PreStop is called immediately before a container + is terminated due to an API request or management event + such as liveness/startup probe failure, preemption, resource + contention, etc. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported + as a LifecycleHandler and kept for the backward compatibility. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. Container + will be restarted if the probe fails. Cannot be updated. More + info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for the + command is root ('/') in the container's filesystem. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. Not + specifying a port here DOES NOT prevent that port from being + exposed. Any port which is listening on the default "0.0.0. + items: + description: ContainerPort represents a network port in a + single container. + properties: + containerPort: + description: Number of port to expose on the pod's IP + address. This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: Number of port to expose on the host. If + specified, this must be a valid port number, 0 < x < + 65536. If HostNetwork is specified, this must match + ContainerPort. Most containers do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a pod + must have a unique name. Name for the port that can + be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe + fails. Cannot be updated. More info: https://kubernetes.' + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for the + command is root ('/') in the container's filesystem. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource resize + policy for the container. + properties: + resourceName: + description: 'Name of the resource to which this resource + resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource + is resized. If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + restartPolicy: + description: RestartPolicy defines the restart behavior of individual + containers in a pod. This field may only be set for init containers, + and the only allowed value is "Always". + type: string + securityContext: + description: SecurityContext defines the security options the + container should be run with. If set, the fields of SecurityContext + override the equivalent fields of PodSecurityContext. + properties: + allowPrivilegeEscalation: + description: AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. + type: string + type: object + type: object + startupProbe: + description: StartupProbe indicates that the Pod has successfully + initialized. If specified, no other probes are executed until + this completes successfully. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for the + command is root ('/') in the container's filesystem. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name. This will + be canonicalized upon output, so case-variant + names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container has + started before liveness probes are initiated. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum value + is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on + the container. Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs + to terminate gracefully upon probe failure. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate a buffer + for stdin in the container runtime. If this is not set, reads + from stdin in the container will always result in EOF. Default + is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close the + stdin channel after it has been opened by a single attach. + When stdin is true the stdin stream will remain open across + multiple attach sessions. + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which the + container''s termination message will be written is mounted + into the container''s filesystem.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should be + populated. File will use the contents of terminationMessagePath + to populate the container status message on both success and + failure. + type: string + tty: + description: Whether this container should allocate a TTY for + itself, also requires 'stdin' to be true. Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices to be + used by the container. + items: + description: volumeDevice describes a mapping of a raw block + device within a container. + properties: + devicePath: + description: devicePath is the path inside of the container + that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other + way around. When not set, MountPropagationNone is used. + This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which might + be configured in the container image. Cannot be updated. + type: string + required: + - name + type: object + type: array + lifecycle: + description: Actions that the management system should take in response + to container lifecycle events. Cannot be updated. + properties: + postStart: + description: PostStart is called immediately after a container + is created. If the handler fails, the container is terminated + and restarted according to its restart policy. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported as a LifecycleHandler + and kept for the backward compatibility. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: PreStop is called immediately before a container + is terminated due to an API request or management event such + as liveness/startup probe failure, preemption, resource contention, + etc. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: Deprecated. TCPSocket is NOT supported as a LifecycleHandler + and kept for the backward compatibility. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: Liveness config for the OpenTelemetry Collector except + the probe handler which is auto generated from the health extension + of the collector. + properties: + failureThreshold: + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. + format: int32 + type: integer + initialDelaySeconds: + description: 'Number of seconds after the container has started + before liveness probes are initiated. Defaults to 0 seconds. + Minimum value is 0. More info: https://kubernetes.' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. + format: int64 + type: integer + timeoutSeconds: + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + managementState: + default: managed + description: ManagementState defines if the CR should be managed by + the operator or not. Default is managed. + enum: + - managed + - unmanaged + type: string + maxReplicas: + description: 'MaxReplicas sets an upper bound to the autoscaling feature. + If MaxReplicas is set autoscaling is enabled. Deprecated: use "OpenTelemetryCollector.Spec.Autoscaler.MaxReplicas" + instead.' + format: int32 + type: integer + minReplicas: + description: 'MinReplicas sets a lower bound to the autoscaling feature. Set + this if you are using autoscaling. It must be at least 1 Deprecated: + use "OpenTelemetryCollector.Spec.Autoscaler.MinReplicas" instead.' + format: int32 + type: integer + mode: + description: Mode represents how the collector should be deployed + (deployment, daemonset, statefulset or sidecar) + enum: + - daemonset + - deployment + - sidecar + - statefulset + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector to schedule OpenTelemetry Collector pods. + This is only relevant to daemonset, statefulset, and deployment + mode + type: object + observability: + description: ObservabilitySpec defines how telemetry data gets handled. + properties: + metrics: + description: Metrics defines the metrics configuration for operands. + properties: + enableMetrics: + description: EnableMetrics specifies if ServiceMonitor should + be created for the OpenTelemetry Collector and Prometheus + Exporters. The operator.observability. + type: boolean + type: object + type: object + podAnnotations: + additionalProperties: + type: string + description: PodAnnotations is the set of annotations that will be + attached to Collector and Target Allocator pods. + type: object + podDisruptionBudget: + description: PodDisruptionBudget specifies the pod disruption budget + configuration to use for the OpenTelemetryCollector workload. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at most "maxUnavailable" + pods selected by "selector" are unavailable after the eviction, + i.e. even in absence of the evicted pod. + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: An eviction is allowed if at least "minAvailable" + pods selected by "selector" will still be available after the + eviction, i.e. even in the absence of the evicted pod. + x-kubernetes-int-or-string: true + type: object + podSecurityContext: + description: PodSecurityContext configures the pod security context + for the opentelemetry-collector pod, when running as a deployment, + daemonset, or statefulset. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1." + format: int64 + type: integer + fsGroupChangePolicy: + description: fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for th + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + type: string + type: object + type: object + ports: + description: Ports allows a set of ports to be exposed by the underlying + v1.Service. By default, the operator will attempt to infer the required + ports by parsing the .Spec. + items: + description: ServicePort contains information on service's port. + properties: + appProtocol: + description: The application protocol for this port. This is + used as a hint for implementations to offer richer behavior + for protocols that they understand. This field follows standard + Kubernetes label syntax. + type: string + name: + description: The name of this port within the service. This + must be a DNS_LABEL. All ports within a ServiceSpec must have + unique names. + type: string + nodePort: + description: The port on each node on which this service is + exposed when type is NodePort or LoadBalancer. Usually assigned + by the system. + format: int32 + type: integer + port: + description: The port that will be exposed by this service. + format: int32 + type: integer + protocol: + default: TCP + description: The IP protocol for this port. Supports "TCP", + "UDP", and "SCTP". Default is TCP. + type: string + targetPort: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the pods + targeted by the service. Number must be in the range 1 to + 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: array + x-kubernetes-list-type: atomic + priorityClassName: + description: If specified, indicates the pod's priority. If not specified, + the pod priority will be default or zero if there is no default. + type: string + replicas: + description: Replicas is the number of pod instances for the underlying + OpenTelemetry Collector. Set this if your are not using autoscaling + format: int32 + type: integer + resources: + description: Resources to set on the OpenTelemetry Collector pods. + properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims + of the Pod where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources + allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + securityContext: + description: SecurityContext configures the container security context + for the opentelemetry-collector container. + properties: + allowPrivilegeEscalation: + description: AllowPrivilegeEscalation controls whether a process + can gain more privileges than its parent process. This bool + directly controls if the no_new_privs flag will be set on the + container process. + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container + runtime. Note that this field cannot be set when spec.os.name + is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in privileged + containers are essentially equivalent to root on the host. Defaults + to false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use for + the containers. The default is DefaultProcMount which uses the + container runtime defaults for readonly paths and masked paths. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in PodSecurityContext. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in PodSecurityContext. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. If + seccomp options are provided at both the pod & container level, + the container options override the pod options. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will + be used. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + type: string + type: object + type: object + serviceAccount: + description: ServiceAccount indicates the name of an existing service + account to use with this instance. When set, the operator will not + automatically create a ServiceAccount for the collector. + type: string + targetAllocator: + description: TargetAllocator indicates a value which determines whether + to spawn a target allocation resource or not. + properties: + affinity: + description: If specified, indicates the pod's scheduling constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector in + the specified namespaces, where co-located + is defined as running on a node whose ' + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-locate + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose ' + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector in + the specified namespaces, where co-located + is defined as running on a node whose ' + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-locate + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. + items: + type: string + type: array + topologyKey: + description: 'This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose ' + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + allocationStrategy: + description: AllocationStrategy determines which strategy the + target allocator should use for allocation. The current options + are least-weighted and consistent-hashing. The default option + is least-weighted + enum: + - least-weighted + - consistent-hashing + type: string + enabled: + description: Enabled indicates whether to use a target allocation + mechanism for Prometheus targets or not. + type: boolean + env: + description: ENV vars to set on the OpenTelemetry TargetAllocator's + Pods. These can then in certain cases be consumed in the config + file for the TargetAllocator. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + filterStrategy: + description: FilterStrategy determines how to filter targets before + allocating them among the collectors. The only current option + is relabel-config (drops targets based on prom relabel_config). + type: string + image: + description: Image indicates the container image to use for the + OpenTelemetry TargetAllocator. + type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector to schedule OpenTelemetry TargetAllocator + pods. + type: object + prometheusCR: + description: PrometheusCR defines the configuration for the retrieval + of PrometheusOperator CRDs ( servicemonitor.monitoring.coreos.com/v1 + and podmonitor.monitoring.coreos.com/v1 ) retrieval. + properties: + enabled: + description: Enabled indicates whether to use a PrometheusOperator + custom resources as targets or not. + type: boolean + podMonitorSelector: + additionalProperties: + type: string + description: PodMonitors to be selected for target discovery. + This is a map of {key,value} pairs. Each {key,value} in + the map is going to exactly match a label in a PodMonitor's + meta labels. + type: object + scrapeInterval: + default: 30s + description: "Interval between consecutive scrapes. Equivalent + to the same setting on the Prometheus CRD. \n Default: \"30s\"" + format: duration + type: string + serviceMonitorSelector: + additionalProperties: + type: string + description: ServiceMonitors to be selected for target discovery. + This is a map of {key,value} pairs. Each {key,value} in + the map is going to exactly match a label in a ServiceMonitor's + meta labels. + type: object + type: object + replicas: + description: Replicas is the number of pod instances for the underlying + TargetAllocator. This should only be set to a value other than + 1 if a strategy that allows for high availability is chosen. + format: int32 + type: integer + resources: + description: Resources to set on the OpenTelemetryTargetAllocator + containers. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + serviceAccount: + description: ServiceAccount indicates the name of an existing + service account to use with this instance. When set, the operator + will not automatically create a ServiceAccount for the TargetAllocator. + type: string + tolerations: + description: Toleration embedded kubernetes pod configuration + option, controls how pods can be scheduled with matching taints + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to + the value. Valid operators are Exists and Equal. Defaults + to Equal. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: TopologySpreadConstraints embedded kubernetes pod + configuration option, controls how pods are spread across your + cluster among failure-domains such as regions, zones, nodes, + and other user-defined top + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine + the number of pods in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys to + select the pods over which spreading will be calculated. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. + format: int32 + type: integer + minDomains: + description: MinDomains indicates a minimum number of eligible + domains. + format: int32 + type: integer + nodeAffinityPolicy: + description: NodeAffinityPolicy indicates how we will treat + Pod's nodeAffinity/nodeSelector when calculating pod topology + spread skew. + type: string + nodeTaintsPolicy: + description: NodeTaintsPolicy indicates how we will treat + node taints when calculating pod topology spread skew. + type: string + topologyKey: + description: TopologyKey is the key of node labels. Nodes + that have a label with this key and identical values are + considered to be in the same topology. + type: string + whenUnsatisfiable: + description: WhenUnsatisfiable indicates how to deal with + a pod if it doesn't satisfy the spread constraint. - DoNotSchedule + (default) tells the scheduler not to schedule it. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + terminationGracePeriodSeconds: + description: Duration in seconds the pod needs to terminate gracefully + upon probe failure. + format: int64 + type: integer + tolerations: + description: Toleration to schedule OpenTelemetry Collector pods. + This is only relevant to daemonset, statefulset, and deployment + mode + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: TopologySpreadConstraints embedded kubernetes pod configuration + option, controls how pods are spread across your cluster among failure-domains + such as regions, zones, nodes, and other user-defined top + items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching pods. Pods + that match this label selector are counted to determine the + number of pods in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists or + DoesNotExist, the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys to select + the pods over which spreading will be calculated. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: MaxSkew describes the degree to which pods may + be unevenly distributed. + format: int32 + type: integer + minDomains: + description: MinDomains indicates a minimum number of eligible + domains. + format: int32 + type: integer + nodeAffinityPolicy: + description: NodeAffinityPolicy indicates how we will treat + Pod's nodeAffinity/nodeSelector when calculating pod topology + spread skew. + type: string + nodeTaintsPolicy: + description: NodeTaintsPolicy indicates how we will treat node + taints when calculating pod topology spread skew. + type: string + topologyKey: + description: TopologyKey is the key of node labels. Nodes that + have a label with this key and identical values are considered + to be in the same topology. + type: string + whenUnsatisfiable: + description: WhenUnsatisfiable indicates how to deal with a + pod if it doesn't satisfy the spread constraint. - DoNotSchedule + (default) tells the scheduler not to schedule it. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + updateStrategy: + description: UpdateStrategy represents the strategy the operator will + take replacing existing DaemonSet pods with new pods https://kubernetes. + properties: + rollingUpdate: + description: 'Rolling update config params. Present only if type + = "RollingUpdate". --- TODO: Update this to follow our convention + for oneOf, whatever we decide it to be. Same as Deployment `strategy.' + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: The maximum number of nodes with an existing + available DaemonSet pod that can have an updated DaemonSet + pod during during an update. + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: The maximum number of DaemonSet pods that can + be unavailable during the update. + x-kubernetes-int-or-string: true + type: object + type: + description: Type of daemon set update. Can be "RollingUpdate" + or "OnDelete". Default is RollingUpdate. + type: string + type: object + upgradeStrategy: + description: UpgradeStrategy represents how the operator will handle + upgrades to the CR when a newer version of the operator is deployed + enum: + - automatic + - none + type: string + volumeClaimTemplates: + description: VolumeClaimTemplates will provide stable storage using + PersistentVolumes. Only available when the mode=statefulset. + items: + description: PersistentVolumeClaim is a user's request for and claim + to a persistent volume + properties: + apiVersion: + description: APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. + type: string + kind: + description: Kind is a string value representing the REST resource + this object represents. Servers may infer this from the endpoint + the client submits requests to. Cannot be updated. In CamelCase. + type: string + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + description: 'spec defines the desired characteristics of a + volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, the + specified Kind must be in the core API group. For + any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: dataSourceRef specifies the object from which + to populate the volume with data, if a non-empty volume + is desired. + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, the + specified Kind must be in the core API group. For + any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s. + type: string + required: + - kind + - name + type: object + resources: + description: resources represents the minimum resources + the volume should have. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate." + items: + description: ResourceClaim references one entry in + PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where + this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of + compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. + type: object + type: object + selector: + description: selector is a label query over volumes to consider + for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not + included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore that + update and let other controllers handle it. + type: string + description: allocatedResourceStatuses stores status of + resource being resized for the given PVC. Key names follow + standard Kubernetes label syntax. + type: object + x-kubernetes-map-type: granular + allocatedResources: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: allocatedResources tracks the resources allocated + to a PVC including its capacity. Key names follow standard + Kubernetes label syntax. + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: capacity represents the actual resources of + the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contains details + about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed the + condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the condition + transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be a + short, machine understandable string that gives + the reason for condition's last transition. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType is + a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + type: object + type: object + type: array + x-kubernetes-list-type: atomic + volumeMounts: + description: VolumeMounts represents the mount points to use in the + underlying collector deployment(s) + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume should + be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are propagated + from the host to container and the other way around. When + not set, MountPropagationNone is used. This field is beta + in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which the + container's volume should be mounted. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-type: atomic + volumes: + description: Volumes represents which volumes to use in the underlying + collector deployment(s). + items: + description: Volume represents a named volume in a pod that may + be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs".' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount + by volume name. Examples: For volume /dev/sda1, you specify + the partition as "1".' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent disk + resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount on + the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: None, + Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in the + blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the blob + storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must be + a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single blob + disk per storage account Managed: azure managed data + disk (only in managed availability set).' + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service mount + on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host that + shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is the + path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is empty. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is optional: User is the rados user name, + default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached and + mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred to + be "ext4" if unspecified.' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + description: 'volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should populate + this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used to + set permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value between + 0 and 511.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair in + the Data field of the referenced ConfigMap will be projected + into the volume as a file whose name is the key and content + is the value. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents ephemeral + storage that is handled by certain external CSI drivers (Beta + feature). + properties: + driver: + description: driver is the name of the CSI driver that handles + this volume. Consult with your admin for the correct name + as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the associated + CSI driver which will determine the default filesystem + to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to the + secret object containing sensitive information to pass + to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific properties + that are passed to the CSI driver. Consult your driver's + documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the pod + that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created files + by default. Must be a Optional: mode bits used to set + permissions on created files by default.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the pod: + only annotations, labels, name and namespace are + supported.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + description: 'Optional: mode bits used to set permissions + on this file, must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative path + name of the file to be created. Must not be absolute + or contain the ''..'' path. Must be utf-8 encoded. + The first item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory that + shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: medium represents what type of storage medium + should back this directory. The default is "" which means + to use the node's default medium. Must be an empty string + (default) or Memory. + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: sizeLimit is the total amount of local storage + required for this EmptyDir volume. The size limit is also + applicable for memory medium. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: ephemeral represents a volume that is handled by + a cluster storage driver. + properties: + volumeClaimTemplate: + description: Will be used to create a stand-alone PVC to + provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. + properties: + metadata: + description: May contain labels and annotations that + will be copied into the PVC when creating it. No other + fields are allowed and will be rejected during validation. + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the PVC + that gets created from this template. + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API + group. For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: dataSourceRef specifies the object + from which to populate the volume with data, if + a non-empty volume is desired. + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API + group. For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace + is specified, a gateway.networking.k8s. + type: string + required: + - kind + - name + type: object + resources: + description: resources represents the minimum resources + the volume should have. + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used + by this container. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name + of one entry in pod.spec.resourceClaims + of the Pod where this field is used. + It makes that resource available inside + a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum + amount of compute resources required. + type: object + type: object + selector: + description: selector is a label query over volumes + to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: 'storageClassName is the name of the + StorageClass required by the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem + is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that is + attached to a kubelet's host machine and then exposed to the + pod. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs and + lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use for + this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". The default filesystem depends + on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds extra + command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if no + secret object is specified.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached to + a kubelet's host machine. This depends on the Flocker control + service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored as + metadata -> name on the dataset for Flocker should be + considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. This + is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://kubernetes.' + properties: + fsType: + description: 'fsType is filesystem type of the volume that + you want to mount. Tip: Ensure that the filesystem type + is supported by the host operating system. Examples: "ext4", + "xfs", "ntfs".' + type: string + partition: + description: 'partition is the partition in the volume that + you want to mount. If omitted, the default is to mount + by volume name. Examples: For volume /dev/sda1, you specify + the partition as "1".' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource in + GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated.' + properties: + directory: + description: directory is the target directory name. Must + not contain or start with '..'. If '.' is supplied, the + volume directory will be the git repository. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More info: + https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs volume + to be mounted with read-only permissions. Defaults to + false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: hostPath represents a pre-existing file or directory + on the host machine that is directly exposed to the container. + properties: + path: + description: 'path of the directory on the host. If the + path is a symlink, it will follow the link to the real + path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that is + attached to a kubelet''s host machine and then exposed to + the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support iSCSI + Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support iSCSI + Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs".' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that uses + an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. The + portal is either an IP or ip_addr:port if the port is + other than default (typically TCP ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI target + and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. The Portal + is either an IP or ip_addr:port if the port is other than + default (typically TCP ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL and unique + within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host that shares + a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. More + info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export to + be mounted with read-only permissions. Defaults to false. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of the + NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents a + reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting in + VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set permissions + on created files by default. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along with + other supported volume types + properties: + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be + an octal value between 0000 and 0777 or + a decimal value between 0 and 511.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' + path. Must be utf-8 encoded. The first + item of the relative path must not start + with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and requests + (limits.cpu, limits.memory, requests.cpu + and requests.memory) are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret data + to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. + Must be an octal value between 0000 and + 0777 or a decimal value between 0 and + 511.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be + an absolute path. May not contain the + path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional field specify whether the + Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is information about + the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must identify + itself with an identifier specified in the audience + of the token, and otherwise should reject the + token. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, the + kubelet volume plugin will proactively rotate + the service account token. + format: int64 + type: integer + path: + description: path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is no + group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults to + false. + type: boolean + registry: + description: registry represents a single or multiple Quobyte + Registry services specified as a string as host:port pair + (multiple entries are separated with commas) which acts + as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume in the + Backend Used with dynamically provisioned Quobyte volumes, + value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to serivceaccount + user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount on the + host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs".' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication secret + for RBDUser. If provided overrides keyring. Default is + nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + user: + description: 'user is the rados user name. Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for ScaleIO + user and other sensitive information. If this is not provided, + Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage for + a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: system is the name of the storage system as + configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to + set permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value between + 0 and 511.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to + set permissions on this file. Must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511.' + format: int32 + type: integer + path: + description: path is the relative path of the file + to map the key to. May not be an absolute path. + May not contain the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. Must + be a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for obtaining + the StorageOS API credentials. If not specified, default + values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + description: volumeName is the human-readable name of the + StorageOS volume. Volume names are only unique within + a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of the + volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must be + a filesystem type supported by the host operating system. + Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy Based + Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies vSphere + volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-type: atomic + type: object + status: + description: OpenTelemetryCollectorStatus defines the observed state of + OpenTelemetryCollector. + properties: + image: + description: Image indicates the container image to use for the OpenTelemetry + Collector. + type: string + messages: + description: 'Messages about actions performed by the operator on + this resource. Deprecated: use Kubernetes events instead.' + items: + type: string + type: array + x-kubernetes-list-type: atomic + replicas: + description: 'Replicas is currently not being set and might be removed + in the next version. Deprecated: use "OpenTelemetryCollector.Status.Scale.Replicas" + instead.' + format: int32 + type: integer + scale: + description: Scale is the OpenTelemetryCollector's scale subresource + status. + properties: + replicas: + description: The total number non-terminated pods targeted by + this OpenTelemetryCollector's deployment or statefulSet. + format: int32 + type: integer + selector: + description: The selector used to match the OpenTelemetryCollector's + deployment or statefulSet pods. + type: string + statusReplicas: + description: StatusReplicas is the number of pods targeted by + this OpenTelemetryCollector's with a Ready Condition / Total + number of non-terminated pods targeted by this OpenTelemetryCollector's + (their labels matc + type: string + type: object + version: + description: Version of the managed OpenTelemetry Collector (operand) + type: string + type: object + type: object + served: true + storage: true + subresources: + scale: + labelSelectorPath: .status.scale.selector + specReplicasPath: .spec.replicas + statusReplicasPath: .status.scale.replicas + status: {} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetryinstrumentation.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetryinstrumentation.yaml new file mode 100644 index 00000000..d54c4534 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/crds/crd-opentelemetryinstrumentation.yaml @@ -0,0 +1,1627 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + name: instrumentations.opentelemetry.io +spec: + group: opentelemetry.io + names: + kind: Instrumentation + listKind: InstrumentationList + plural: instrumentations + shortNames: + - otelinst + - otelinsts + singular: instrumentation + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.exporter.endpoint + name: Endpoint + type: string + - jsonPath: .spec.sampler.type + name: Sampler + type: string + - jsonPath: .spec.sampler.argument + name: Sampler Arg + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: Instrumentation is the spec for OpenTelemetry instrumentation. + properties: + apiVersion: + description: APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. + type: string + kind: + description: Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. + type: string + metadata: + type: object + spec: + description: InstrumentationSpec defines the desired state of OpenTelemetry + SDK and instrumentation. + properties: + apacheHttpd: + description: ApacheHttpd defines configuration for Apache HTTPD auto-instrumentation. + properties: + attrs: + description: 'Attrs defines Apache HTTPD agent specific attributes. + The precedence is: `agent default attributes` > `instrument + spec attributes` . Attributes are documented at https://github.' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + configPath: + description: Location of Apache HTTPD server configuration. Needed + only if different from default "/usr/local/apache2/conf" + type: string + env: + description: Env defines Apache HTTPD specific env vars. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Image is a container image with Apache SDK and auto-instrumentation. + type: string + resourceRequirements: + description: Resources describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + version: + description: Apache HTTPD server version. One of 2.4 or 2.2. Default + is 2.4 + type: string + volumeLimitSize: + anyOf: + - type: integer + - type: string + description: VolumeSizeLimit defines size limit for volume used + for auto-instrumentation. The default size is 200Mi. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + dotnet: + description: DotNet defines configuration for DotNet auto-instrumentation. + properties: + env: + description: Env defines DotNet specific env vars. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Image is a container image with DotNet SDK and auto-instrumentation. + type: string + resourceRequirements: + description: Resources describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + volumeLimitSize: + anyOf: + - type: integer + - type: string + description: VolumeSizeLimit defines size limit for volume used + for auto-instrumentation. The default size is 200Mi. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + env: + description: Env defines common env vars. + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + exporter: + description: Exporter defines exporter configuration. + properties: + endpoint: + description: Endpoint is address of the collector with OTLP endpoint. + type: string + type: object + go: + description: Go defines configuration for Go auto-instrumentation. + properties: + env: + description: Env defines Go specific env vars. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Image is a container image with Go SDK and auto-instrumentation. + type: string + resourceRequirements: + description: Resources describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + volumeLimitSize: + anyOf: + - type: integer + - type: string + description: VolumeSizeLimit defines size limit for volume used + for auto-instrumentation. The default size is 200Mi. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + java: + description: Java defines configuration for java auto-instrumentation. + properties: + env: + description: Env defines java specific env vars. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Image is a container image with javaagent auto-instrumentation + JAR. + type: string + resources: + description: Resources describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + volumeLimitSize: + anyOf: + - type: integer + - type: string + description: VolumeSizeLimit defines size limit for volume used + for auto-instrumentation. The default size is 200Mi. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + nginx: + description: Nginx defines configuration for Nginx auto-instrumentation. + properties: + attrs: + description: 'Attrs defines Nginx agent specific attributes. The + precedence order is: `agent default attributes` > `instrument + spec attributes` . Attributes are documented at https://github.' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + configFile: + description: Location of Nginx configuration file. Needed only + if different from default "/etx/nginx/nginx.conf" + type: string + env: + description: Env defines Nginx specific env vars. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Image is a container image with Nginx SDK and auto-instrumentation. + type: string + resourceRequirements: + description: Resources describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + volumeLimitSize: + anyOf: + - type: integer + - type: string + description: VolumeSizeLimit defines size limit for volume used + for auto-instrumentation. The default size is 200Mi. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + nodejs: + description: NodeJS defines configuration for nodejs auto-instrumentation. + properties: + env: + description: Env defines nodejs specific env vars. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Image is a container image with NodeJS SDK and auto-instrumentation. + type: string + resourceRequirements: + description: Resources describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + volumeLimitSize: + anyOf: + - type: integer + - type: string + description: VolumeSizeLimit defines size limit for volume used + for auto-instrumentation. The default size is 200Mi. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + propagators: + description: Propagators defines inter-process context propagation + configuration. Values in this list will be set in the OTEL_PROPAGATORS + env var. Enum=tracecontext;baggage;b3;b3multi;jaeger;xray;ottrace;none + items: + description: Propagator represents the propagation type. + enum: + - tracecontext + - baggage + - b3 + - b3multi + - jaeger + - xray + - ottrace + - none + type: string + type: array + python: + description: Python defines configuration for python auto-instrumentation. + properties: + env: + description: Env defines python specific env vars. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Image is a container image with Python SDK and auto-instrumentation. + type: string + resourceRequirements: + description: Resources describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of compute + resources required. + type: object + type: object + volumeLimitSize: + anyOf: + - type: integer + - type: string + description: VolumeSizeLimit defines size limit for volume used + for auto-instrumentation. The default size is 200Mi. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + resource: + description: Resource defines the configuration for the resource attributes, + as defined by the OpenTelemetry specification. + properties: + addK8sUIDAttributes: + description: AddK8sUIDAttributes defines whether K8s UID attributes + should be collected (e.g. k8s.deployment.uid). + type: boolean + resourceAttributes: + additionalProperties: + type: string + description: 'Attributes defines attributes that are added to + the resource. For example environment: dev' + type: object + type: object + sampler: + description: Sampler defines sampling configuration. + properties: + argument: + description: Argument defines sampler argument. The value depends + on the sampler type. For instance for parentbased_traceidratio + sampler type it is a number in range [0..1] e.g. 0.25. + type: string + type: + description: Type defines sampler type. The value will be set + in the OTEL_TRACES_SAMPLER env var. The value can be for instance + parentbased_always_on, parentbased_always_off, parentbased_traceidratio... + enum: + - always_on + - always_off + - traceidratio + - parentbased_always_on + - parentbased_always_off + - parentbased_traceidratio + - jaeger_remote + - xray + type: string + type: object + type: object + status: + description: InstrumentationStatus defines status of the instrumentation. + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/README.md b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/README.md new file mode 100644 index 00000000..3bfe3ab8 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/README.md @@ -0,0 +1,7 @@ +# Examples of chart configuration + +Here is a collection of common configurations for the OpenTelemetry Operator. Each folder contains an example `values.yaml` and the resulting configurations that are generated by the opentelemetry-operator helm chart. + +- [Default configuration](default) + +The manifests are rendered using the `helm template` command and the specific example folder's values.yaml. diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/admission-webhooks/operator-webhook-with-cert-manager.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/admission-webhooks/operator-webhook-with-cert-manager.yaml new file mode 100644 index 00000000..04fcd065 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/admission-webhooks/operator-webhook-with-cert-manager.yaml @@ -0,0 +1,184 @@ +--- +# Source: opentelemetry-operator/templates/admission-webhooks/operator-webhook-with-cert-manager.yaml +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + annotations: + cert-manager.io/inject-ca-from: default/example-opentelemetry-operator-serving-cert + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: webhook + name: example-opentelemetry-operator-mutation +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: example-opentelemetry-operator-webhook + namespace: default + path: /mutate-opentelemetry-io-v1alpha1-instrumentation + failurePolicy: Fail + name: minstrumentation.kb.io + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - instrumentations + scope: Namespaced + sideEffects: None + timeoutSeconds: 10 + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: example-opentelemetry-operator-webhook + namespace: default + path: /mutate-opentelemetry-io-v1alpha1-opentelemetrycollector + failurePolicy: Fail + name: mopentelemetrycollector.kb.io + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - opentelemetrycollectors + scope: Namespaced + sideEffects: None + timeoutSeconds: 10 + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: example-opentelemetry-operator-webhook + namespace: default + path: /mutate-v1-pod + failurePolicy: Ignore + name: mpod.kb.io + rules: + - apiGroups: + - "" + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - pods + scope: Namespaced + sideEffects: None + timeoutSeconds: 10 +--- +# Source: opentelemetry-operator/templates/admission-webhooks/operator-webhook-with-cert-manager.yaml +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + annotations: + cert-manager.io/inject-ca-from: default/example-opentelemetry-operator-serving-cert + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: webhook + name: example-opentelemetry-operator-validation +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: example-opentelemetry-operator-webhook + namespace: default + path: /validate-opentelemetry-io-v1alpha1-instrumentation + failurePolicy: Fail + name: vinstrumentationcreateupdate.kb.io + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - instrumentations + scope: Namespaced + sideEffects: None + timeoutSeconds: 10 + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: example-opentelemetry-operator-webhook + namespace: default + path: /validate-opentelemetry-io-v1alpha1-instrumentation + failurePolicy: Ignore + name: vinstrumentationdelete.kb.io + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - DELETE + resources: + - instrumentations + scope: Namespaced + sideEffects: None + timeoutSeconds: 10 + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: example-opentelemetry-operator-webhook + namespace: default + path: /validate-opentelemetry-io-v1alpha1-opentelemetrycollector + failurePolicy: Fail + name: vopentelemetrycollectorcreateupdate.kb.io + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - opentelemetrycollectors + scope: Namespaced + sideEffects: None + timeoutSeconds: 10 + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: example-opentelemetry-operator-webhook + namespace: default + path: /validate-opentelemetry-io-v1alpha1-opentelemetrycollector + failurePolicy: Ignore + name: vopentelemetrycollectordelete.kb.io + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - DELETE + resources: + - opentelemetrycollectors + scope: Namespaced + sideEffects: None + timeoutSeconds: 10 diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/certmanager.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/certmanager.yaml new file mode 100644 index 00000000..c4b147be --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/certmanager.yaml @@ -0,0 +1,41 @@ +--- +# Source: opentelemetry-operator/templates/certmanager.yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: webhook + name: example-opentelemetry-operator-serving-cert + namespace: default +spec: + dnsNames: + - example-opentelemetry-operator-webhook.default.svc + - example-opentelemetry-operator-webhook.default.svc.cluster.local + issuerRef: + kind: Issuer + name: example-opentelemetry-operator-selfsigned-issuer + secretName: example-opentelemetry-operator-controller-manager-service-cert + subject: + organizationalUnits: + - example-opentelemetry-operator +--- +# Source: opentelemetry-operator/templates/certmanager.yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: webhook + name: example-opentelemetry-operator-selfsigned-issuer + namespace: default +spec: + selfSigned: {} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/clusterrole.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/clusterrole.yaml new file mode 100644 index 00000000..273fb7f0 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/clusterrole.yaml @@ -0,0 +1,293 @@ +--- +# Source: opentelemetry-operator/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + name: example-opentelemetry-operator-manager +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - list + - watch + - apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - daemonsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - replicasets + verbs: + - get + - list + - watch + - apiGroups: + - apps + resources: + - statefulsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - list + - update + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + - podmonitors + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - opentelemetry.io + resources: + - instrumentations + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - opentelemetry.io + resources: + - opentelemetrycollectors + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - opentelemetry.io + resources: + - opentelemetrycollectors/finalizers + verbs: + - get + - patch + - update + - apiGroups: + - opentelemetry.io + resources: + - opentelemetrycollectors/status + verbs: + - get + - patch + - update + - apiGroups: + - opentelemetry.io + resources: + - opampbridges + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - opentelemetry.io + resources: + - opampbridges/finalizers + verbs: + - get + - patch + - update + - apiGroups: + - opentelemetry.io + resources: + - opampbridges/status + verbs: + - get + - patch + - update + - apiGroups: + - route.openshift.io + resources: + - routes + - routes/custom-host + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - get + - list + - watch + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +--- +# Source: opentelemetry-operator/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + name: example-opentelemetry-operator-metrics +rules: + - nonResourceURLs: + - /metrics + verbs: + - get +--- +# Source: opentelemetry-operator/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + name: example-opentelemetry-operator-proxy +rules: + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/clusterrolebinding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/clusterrolebinding.yaml new file mode 100644 index 00000000..36f03bbb --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/clusterrolebinding.yaml @@ -0,0 +1,42 @@ +--- +# Source: opentelemetry-operator/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + name: example-opentelemetry-operator-manager +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: example-opentelemetry-operator-manager +subjects: + - kind: ServiceAccount + name: opentelemetry-operator + namespace: default +--- +# Source: opentelemetry-operator/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + name: example-opentelemetry-operator-proxy +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: example-opentelemetry-operator-proxy +subjects: + - kind: ServiceAccount + name: opentelemetry-operator + namespace: default diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/deployment.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/deployment.yaml new file mode 100644 index 00000000..28e5f5a6 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/deployment.yaml @@ -0,0 +1,104 @@ +--- +# Source: opentelemetry-operator/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + name: example-opentelemetry-operator + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/component: controller-manager + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/component: controller-manager + spec: + hostNetwork: false + containers: + - args: + - --metrics-addr=0.0.0.0:8080 + - --enable-leader-election + - --health-probe-addr=:8081 + - --webhook-port=9443 + - --collector-image=otel/opentelemetry-collector-contrib:0.89.0 + command: + - /manager + env: + - name: ENABLE_WEBHOOKS + value: "true" + image: "ghcr.io/open-telemetry/opentelemetry-operator/opentelemetry-operator:v0.89.0" + name: manager + ports: + - containerPort: 8080 + name: metrics + protocol: TCP + - containerPort: 9443 + name: webhook-server + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 64Mi + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8080/ + - --logtostderr=true + - --v=0 + image: "quay.io/brancz/kube-rbac-proxy:v0.15.0" + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + protocol: TCP + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 5m + memory: 64Mi + serviceAccountName: opentelemetry-operator + terminationGracePeriodSeconds: 10 + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: example-opentelemetry-operator-controller-manager-service-cert + securityContext: + fsGroup: 65532 + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/role.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/role.yaml new file mode 100644 index 00000000..0705842e --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/role.yaml @@ -0,0 +1,42 @@ +--- +# Source: opentelemetry-operator/templates/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + name: example-opentelemetry-operator-leader-election + namespace: default +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/rolebinding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/rolebinding.yaml new file mode 100644 index 00000000..a0e1584d --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/rolebinding.yaml @@ -0,0 +1,22 @@ +--- +# Source: opentelemetry-operator/templates/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + name: example-opentelemetry-operator-leader-election + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: example-opentelemetry-operator-leader-election +subjects: + - kind: ServiceAccount + name: opentelemetry-operator + namespace: default diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/service.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/service.yaml new file mode 100644 index 00000000..ad52dae7 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/service.yaml @@ -0,0 +1,49 @@ +--- +# Source: opentelemetry-operator/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + name: example-opentelemetry-operator + namespace: default +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + - name: metrics + port: 8080 + protocol: TCP + targetPort: metrics + selector: + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/component: controller-manager +--- +# Source: opentelemetry-operator/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + name: example-opentelemetry-operator-webhook + namespace: default +spec: + ports: + - port: 443 + protocol: TCP + targetPort: webhook-server + selector: + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/component: controller-manager diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/serviceaccount.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/serviceaccount.yaml new file mode 100644 index 00000000..9b9b0ce7 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/serviceaccount.yaml @@ -0,0 +1,14 @@ +--- +# Source: opentelemetry-operator/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: opentelemetry-operator + namespace: default + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/tests/test-certmanager-connection.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/tests/test-certmanager-connection.yaml new file mode 100644 index 00000000..c6270065 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/tests/test-certmanager-connection.yaml @@ -0,0 +1,37 @@ +--- +# Source: opentelemetry-operator/templates/tests/test-certmanager-connection.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "example-opentelemetry-operator-cert-manager" + namespace: default + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: webhook + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: "busybox:latest" + env: + - name: CERT_MANAGER_CLUSTERIP + value: "cert-manager-webhook" + - name: CERT_MANAGER_PORT + value: "443" + command: + - sh + - -c + # The following shell script tests if the cert-manager service is up. If the service is up, when we try + # to wget its exposed port, we will get an HTTP error 400. + - | + wget_output=$(wget -q "$CERT_MANAGER_CLUSTERIP:$CERT_MANAGER_PORT") + if wget_output=="wget: server returned error: HTTP/1.0 400 Bad Request" + then exit 0 + else exit 1 + fi + restartPolicy: Never diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/tests/test-service-connection.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/tests/test-service-connection.yaml new file mode 100644 index 00000000..cfb9b7e3 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/rendered/tests/test-service-connection.yaml @@ -0,0 +1,74 @@ +--- +# Source: opentelemetry-operator/templates/tests/test-service-connection.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "example-opentelemetry-operator-metrics" + namespace: default + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: "busybox:latest" + env: + - name: MANAGER_METRICS_SERVICE_CLUSTERIP + value: "example-opentelemetry-operator" + - name: MANAGER_METRICS_SERVICE_PORT + value: "8443" + command: + - sh + - -c + # The following shell script tests if the controller-manager-metrics-service is up. + # If the service is up, when we try to wget its exposed port, we will get an HTTP error 400. + - | + wget_output=$(wget -q "$MANAGER_METRICS_SERVICE_CLUSTERIP:$MANAGER_METRICS_SERVICE_PORT") + if wget_output=="wget: server returned error: HTTP/1.0 400 Bad Request" + then exit 0 + else exit 1 + fi + restartPolicy: Never +--- +# Source: opentelemetry-operator/templates/tests/test-service-connection.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "example-opentelemetry-operator-webhook" + namespace: default + labels: + helm.sh/chart: opentelemetry-operator-0.43.0 + app.kubernetes.io/name: opentelemetry-operator + app.kubernetes.io/version: "0.89.0" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: example + app.kubernetes.io/component: controller-manager + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: "busybox:latest" + env: + - name: WEBHOOK_SERVICE_CLUSTERIP + value: "example-opentelemetry-operator-webhook" + - name: WEBHOOK_SERVICE_PORT + value: "443" + command: + - sh + - -c + # The following shell script tests if the webhook service is up. If the service is up, when we try + # to wget its exposed port, we will get an HTTP error 400. + - | + wget_output=$(wget -q "$WEBHOOK_SERVICE_CLUSTERIP:$WEBHOOK_SERVICE_PORT") + if wget_output=="wget: server returned error: HTTP/1.0 400 Bad Request" + then exit 0 + else exit 1 + fi + restartPolicy: Never diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/values.yaml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/examples/default/values.yaml @@ -0,0 +1 @@ + diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/kuttl-test.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/kuttl-test.yaml new file mode 100644 index 00000000..df96ed77 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/kuttl-test.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestSuite +crdDir: ./charts/opentelemetry-operator/crds +timeout: 150 diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/NOTES.txt b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/NOTES.txt new file mode 100644 index 00000000..d7ab3770 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/NOTES.txt @@ -0,0 +1,4 @@ +{{ $.Chart.Name }} has been installed. Check its status by running: + kubectl --namespace {{ .Release.Namespace }} get pods -l "release={{ $.Release.Name }}" + +Visit https://github.com/open-telemetry/opentelemetry-operator for instructions on how to create & configure OpenTelemetryCollector and Instrumentation custom resources by using the Operator. diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/_helpers.tpl b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/_helpers.tpl new file mode 100644 index 00000000..4812314d --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/_helpers.tpl @@ -0,0 +1,117 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "opentelemetry-operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "opentelemetry-operator.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "opentelemetry-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "opentelemetry-operator.labels" -}} +helm.sh/chart: {{ include "opentelemetry-operator.chart" . }} +{{ include "opentelemetry-operator.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "opentelemetry-operator.selectorLabels" -}} +app.kubernetes.io/name: {{ include "opentelemetry-operator.name" . }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "opentelemetry-operator.serviceAccountName" -}} +{{- if .Values.manager.serviceAccount.create }} +{{- default (include "opentelemetry-operator.name" .) .Values.manager.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.manager.serviceAccount.name }} +{{- end }} +{{- end }} + +{{- define "opentelemetry-operator.podAnnotations" -}} +{{- if .Values.manager.podAnnotations }} +{{- .Values.manager.podAnnotations | toYaml }} +{{- end }} +{{- end }} + +{{- define "opentelemetry-operator.podLabels" -}} +{{- if .Values.manager.podLabels }} +{{- .Values.manager.podLabels | toYaml }} +{{- end }} +{{- end }} + +{{/* +Create an ordered name of the MutatingWebhookConfiguration +*/}} +{{- define "opentelemetry-operator.MutatingWebhookName" -}} +{{- printf "%s-%s" (.Values.admissionWebhooks.namePrefix | toString) (include "opentelemetry-operator.fullname" .) | trimPrefix "-" }} +{{- end }} + +{{/* +Return certificate and CA for Webhooks. +It handles variants when a cert has to be generated by Helm, +a cert is loaded from an existing secret or is provided via `.Values` +*/}} +{{- define "opentelemetry-operator.WebhookCert" -}} +{{- $caCertEnc := "" }} +{{- $certCrtEnc := "" }} +{{- $certKeyEnc := "" }} +{{- if .Values.admissionWebhooks.autoGenerateCert.enabled }} +{{- $prevSecret := (lookup "v1" "Secret" .Release.Namespace (default (printf "%s-controller-manager-service-cert" (include "opentelemetry-operator.fullname" .)) .Values.admissionWebhooks.secretName )) }} +{{- if and (not .Values.admissionWebhooks.autoGenerateCert.recreate) $prevSecret }} +{{- $certCrtEnc = index $prevSecret "data" "tls.crt" }} +{{- $certKeyEnc = index $prevSecret "data" "tls.key" }} +{{- $caCertEnc = index $prevSecret "data" "ca.crt" }} +{{- if not $caCertEnc }} +{{- $prevHook := (lookup "admissionregistration.k8s.io/v1" "MutatingWebhookConfiguration" .Release.Namespace (print (include "opentelemetry-operator.MutatingWebhookName" . ) "-mutation")) }} +{{- $caCertEnc = (first $prevHook.webhooks).clientConfig.caBundle }} +{{- end }} +{{- else }} +{{- $altNames := list ( printf "%s-webhook.%s" (include "opentelemetry-operator.fullname" .) .Release.Namespace ) ( printf "%s-webhook.%s.svc" (include "opentelemetry-operator.fullname" .) .Release.Namespace ) -}} +{{- $ca := genCA "opentelemetry-operator-operator-ca" 365 }} +{{- $cert := genSignedCert (include "opentelemetry-operator.fullname" .) nil $altNames 365 $ca }} +{{- $certCrtEnc = b64enc $cert.Cert }} +{{- $certKeyEnc = b64enc $cert.Key }} +{{- $caCertEnc = b64enc $ca.Cert }} +{{- end }} +{{- else }} +{{- $certCrtEnc = b64enc .Values.admissionWebhooks.cert_file }} +{{- $certKeyEnc = b64enc .Values.admissionWebhooks.key_file }} +{{- $caCertEnc = b64enc .Values.admissionWebhooks.ca_file }} +{{- end }} +{{- $result := dict "crt" $certCrtEnc "key" $certKeyEnc "ca" $caCertEnc }} +{{- $result | toYaml }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/admission-webhooks/operator-webhook-with-cert-manager.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/admission-webhooks/operator-webhook-with-cert-manager.yaml new file mode 100644 index 00000000..6c4149e9 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/admission-webhooks/operator-webhook-with-cert-manager.yaml @@ -0,0 +1,233 @@ +{{- if and (.Values.admissionWebhooks.create) (.Values.admissionWebhooks.certManager.enabled) }} +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + annotations: + cert-manager.io/inject-ca-from: {{ printf "%s/%s-serving-cert" .Release.Namespace (include "opentelemetry-operator.fullname" .) }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: webhook + name: {{ template "opentelemetry-operator.MutatingWebhookName" . }}-mutation +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /mutate-opentelemetry-io-v1alpha1-instrumentation + failurePolicy: {{ .Values.admissionWebhooks.failurePolicy }} + name: minstrumentation.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - instrumentations + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /mutate-opentelemetry-io-v1alpha1-opentelemetrycollector + failurePolicy: {{ .Values.admissionWebhooks.failurePolicy }} + name: mopentelemetrycollector.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - opentelemetrycollectors + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + {{- if .Values.admissionWebhooks.enablePodOperationsWebhook }} + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /mutate-v1-pod + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + failurePolicy: {{ .Values.admissionWebhooks.pods.failurePolicy }} + name: mpod.kb.io + rules: + - apiGroups: + - "" + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - pods + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + {{- end }} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + annotations: + cert-manager.io/inject-ca-from: {{ printf "%s/%s-serving-cert" .Release.Namespace (include "opentelemetry-operator.fullname" .) }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: webhook + name: {{ template "opentelemetry-operator.fullname" . }}-validation +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-opentelemetry-io-v1alpha1-instrumentation + failurePolicy: {{ .Values.admissionWebhooks.failurePolicy }} + name: vinstrumentationcreateupdate.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - instrumentations + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-opentelemetry-io-v1alpha1-instrumentation + failurePolicy: Ignore + name: vinstrumentationdelete.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - DELETE + resources: + - instrumentations + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-opentelemetry-io-v1alpha1-opentelemetrycollector + failurePolicy: {{ .Values.admissionWebhooks.failurePolicy }} + name: vopentelemetrycollectorcreateupdate.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - opentelemetrycollectors + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-opentelemetry-io-v1alpha1-opentelemetrycollector + failurePolicy: Ignore + name: vopentelemetrycollectordelete.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - DELETE + resources: + - opentelemetrycollectors + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/admission-webhooks/operator-webhook.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/admission-webhooks/operator-webhook.yaml new file mode 100644 index 00000000..76dbb83c --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/admission-webhooks/operator-webhook.yaml @@ -0,0 +1,265 @@ +{{- if and (.Values.admissionWebhooks.create) (not .Values.admissionWebhooks.certManager.enabled) }} +{{- $cert := fromYaml (include "opentelemetry-operator.WebhookCert" .) }} +{{- $caCertEnc := $cert.ca }} +{{- $certCrtEnc := $cert.crt }} +{{- $certKeyEnc := $cert.key }} +apiVersion: v1 +kind: Secret +type: kubernetes.io/tls +metadata: + annotations: + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/hook-delete-policy": "before-hook-creation" + {{- if .Values.admissionWebhooks.secretAnnotations }} + {{- toYaml .Values.admissionWebhooks.secretAnnotations | nindent 4 }} + {{- end }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: webhook + {{- if .Values.admissionWebhooks.secretLabels }} + {{- toYaml .Values.admissionWebhooks.secretLabels | nindent 4 }} + {{- end }} + name: {{ default (printf "%s-controller-manager-service-cert" (include "opentelemetry-operator.fullname" .)) .Values.admissionWebhooks.secretName }} + namespace: {{ .Release.Namespace }} +data: + tls.crt: {{ $certCrtEnc }} + tls.key: {{ $certKeyEnc }} + ca.crt: {{ $caCertEnc }} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: webhook + name: {{ template "opentelemetry-operator.MutatingWebhookName" . }}-mutation +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + caBundle: {{ $caCertEnc }} + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /mutate-opentelemetry-io-v1alpha1-instrumentation + failurePolicy: {{ .Values.admissionWebhooks.failurePolicy }} + name: minstrumentation.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - instrumentations + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + - admissionReviewVersions: + - v1 + clientConfig: + caBundle: {{ $caCertEnc }} + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /mutate-opentelemetry-io-v1alpha1-opentelemetrycollector + failurePolicy: {{ .Values.admissionWebhooks.failurePolicy }} + name: mopentelemetrycollector.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - opentelemetrycollectors + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + {{- if .Values.admissionWebhooks.enablePodOperationsWebhook }} + - admissionReviewVersions: + - v1 + clientConfig: + caBundle: {{ $caCertEnc }} + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /mutate-v1-pod + failurePolicy: {{ .Values.admissionWebhooks.pods.failurePolicy }} + name: mpod.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - "" + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - pods + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + {{- end }} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + annotations: + cert-manager.io/inject-ca-from: {{ printf "%s/%s-serving-cert" .Release.Namespace (include "opentelemetry-operator.fullname" .) }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: webhook + name: {{ template "opentelemetry-operator.fullname" . }}-validation +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + caBundle: {{ $caCertEnc }} + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-opentelemetry-io-v1alpha1-instrumentation + failurePolicy: {{ .Values.admissionWebhooks.failurePolicy }} + name: vinstrumentationcreateupdate.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - instrumentations + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + - admissionReviewVersions: + - v1 + clientConfig: + caBundle: {{ $caCertEnc }} + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-opentelemetry-io-v1alpha1-instrumentation + failurePolicy: Ignore + name: vinstrumentationdelete.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - DELETE + resources: + - instrumentations + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + - admissionReviewVersions: + - v1 + clientConfig: + caBundle: {{ $caCertEnc }} + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-opentelemetry-io-v1alpha1-opentelemetrycollector + failurePolicy: {{ .Values.admissionWebhooks.failurePolicy }} + name: vopentelemetrycollectorcreateupdate.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - opentelemetrycollectors + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} + - admissionReviewVersions: + - v1 + clientConfig: + caBundle: {{ $caCertEnc }} + service: + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} + path: /validate-opentelemetry-io-v1alpha1-opentelemetrycollector + failurePolicy: Ignore + name: vopentelemetrycollectordelete.kb.io + {{- if .Values.admissionWebhooks.namespaceSelector }} + namespaceSelector: + {{- toYaml .Values.admissionWebhooks.namespaceSelector | nindent 6 }} + {{- end }} + {{- if .Values.admissionWebhooks.objectSelector }} + objectSelector: + {{- toYaml .Values.admissionWebhooks.objectSelector | nindent 6 }} + {{- end }} + rules: + - apiGroups: + - opentelemetry.io + apiVersions: + - v1alpha1 + operations: + - DELETE + resources: + - opentelemetrycollectors + scope: Namespaced + sideEffects: None + timeoutSeconds: {{ .Values.admissionWebhooks.timeoutSeconds }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/certmanager.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/certmanager.yaml new file mode 100644 index 00000000..0b19fe4d --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/certmanager.yaml @@ -0,0 +1,46 @@ +{{- if and .Values.admissionWebhooks.create .Values.admissionWebhooks.certManager.enabled }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + {{- if .Values.admissionWebhooks.certManager.certificateAnnotations }} + annotations: + {{- toYaml .Values.admissionWebhooks.certManager.certificateAnnotations | nindent 4 }} + {{- end }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: webhook + name: {{ template "opentelemetry-operator.fullname" . }}-serving-cert + namespace: {{ .Release.Namespace }} +spec: + dnsNames: + - {{ template "opentelemetry-operator.fullname" . }}-webhook.{{ .Release.Namespace }}.svc + - {{ template "opentelemetry-operator.fullname" . }}-webhook.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + {{- if .Values.admissionWebhooks.certManager.issuerRef }} + {{- toYaml .Values.admissionWebhooks.certManager.issuerRef | nindent 4 }} + {{- else }} + kind: Issuer + name: {{ template "opentelemetry-operator.fullname" . }}-selfsigned-issuer + {{- end }} + secretName: {{ default (printf "%s-controller-manager-service-cert" (include "opentelemetry-operator.fullname" .)) .Values.admissionWebhooks.secretName }} + subject: + organizationalUnits: + - {{ template "opentelemetry-operator.fullname" . }} +{{- if not .Values.admissionWebhooks.certManager.issuerRef }} +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + {{- if .Values.admissionWebhooks.certManager.issuerAnnotations }} + annotations: + {{- toYaml .Values.admissionWebhooks.certManager.issuerAnnotations | nindent 4 }} + {{- end }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: webhook + name: {{ template "opentelemetry-operator.fullname" . }}-selfsigned-issuer + namespace: {{ .Release.Namespace }} +spec: + selfSigned: {} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/clusterrole.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/clusterrole.yaml new file mode 100644 index 00000000..6369ecb5 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/clusterrole.yaml @@ -0,0 +1,282 @@ +{{- if .Values.clusterRole.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }}-manager +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - list + - watch + - apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - daemonsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - replicasets + verbs: + - get + - list + - watch + - apiGroups: + - apps + resources: + - statefulsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - list + - update + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + - podmonitors + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - opentelemetry.io + resources: + - instrumentations + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - opentelemetry.io + resources: + - opentelemetrycollectors + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - opentelemetry.io + resources: + - opentelemetrycollectors/finalizers + verbs: + - get + - patch + - update + - apiGroups: + - opentelemetry.io + resources: + - opentelemetrycollectors/status + verbs: + - get + - patch + - update + - apiGroups: + - opentelemetry.io + resources: + - opampbridges + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - opentelemetry.io + resources: + - opampbridges/finalizers + verbs: + - get + - patch + - update + - apiGroups: + - opentelemetry.io + resources: + - opampbridges/status + verbs: + - get + - patch + - update + - apiGroups: + - route.openshift.io + resources: + - routes + - routes/custom-host + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - get + - list + - watch + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + +{{ if .Values.kubeRBACProxy.enabled }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }}-metrics +rules: + - nonResourceURLs: + - /metrics + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }}-proxy +rules: + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +{{- end }} +{{ end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/clusterrolebinding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..d87d39ff --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/clusterrolebinding.yaml @@ -0,0 +1,36 @@ +{{- if .Values.clusterRole.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }}-manager +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "opentelemetry-operator.fullname" . }}-manager +subjects: + - kind: ServiceAccount + name: {{ template "opentelemetry-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + +{{ if .Values.kubeRBACProxy.enabled }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }}-proxy +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "opentelemetry-operator.fullname" . }}-proxy +subjects: + - kind: ServiceAccount + name: {{ template "opentelemetry-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} +{{ end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/deployment.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/deployment.yaml new file mode 100644 index 00000000..fad51a35 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/deployment.yaml @@ -0,0 +1,166 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "opentelemetry-operator.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller-manager + template: + metadata: + annotations: + {{- if .Values.manager.rolling }} + rollme: {{ randAlphaNum 5 | quote }} + {{- end }} + kubectl.kubernetes.io/default-container: manager + {{- if .Values.manager.podAnnotations }} + {{- include "opentelemetry-operator.podAnnotations" . | nindent 8 }} + {{- end }} + labels: + {{- include "opentelemetry-operator.selectorLabels" . | nindent 8 }} + {{- if .Values.manager.podLabels }} + {{- include "opentelemetry-operator.podLabels" . | nindent 8 }} + {{- end }} + app.kubernetes.io/component: controller-manager + spec: + hostNetwork: {{ .Values.hostNetwork }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName | quote }} + {{- end }} + containers: + - args: + - --metrics-addr=0.0.0.0:{{ .Values.manager.ports.metricsPort }} + {{- if .Values.manager.leaderElection.enabled }} + - --enable-leader-election + {{- end }} + - --health-probe-addr=:{{ .Values.manager.ports.healthzPort }} + {{- if or .Values.admissionWebhooks.create .Values.admissionWebhooks.secretName }} + - --webhook-port={{ .Values.manager.ports.webhookPort }} + {{- end }} + {{- if and .Values.manager.collectorImage.repository .Values.manager.collectorImage.tag }} + - --collector-image={{ .Values.manager.collectorImage.repository }}:{{ .Values.manager.collectorImage.tag }} + {{- end }} + {{- if and .Values.manager.opampBridgeImage.repository .Values.manager.opampBridgeImage.tag }} + - --operator-opamp-bridge-image={{ .Values.manager.opampBridgeImage.repository }}:{{ .Values.manager.opampBridgeImage.tag }} + {{- end }} + {{- if and .Values.manager.targetAllocatorImage.repository .Values.manager.targetAllocatorImage.tag }} + - --target-allocator-image={{ .Values.manager.targetAllocatorImage.repository }}:{{ .Values.manager.targetAllocatorImage.tag }} + {{- end }} + {{- if and .Values.manager.autoInstrumentationImage.java.repository .Values.manager.autoInstrumentationImage.java.tag }} + - --auto-instrumentation-java-image={{ .Values.manager.autoInstrumentationImage.java.repository }}:{{ .Values.manager.autoInstrumentationImage.java.tag }} + {{- end }} + {{- if and .Values.manager.autoInstrumentationImage.nodejs.repository .Values.manager.autoInstrumentationImage.nodejs.tag }} + - --auto-instrumentation-nodejs-image={{ .Values.manager.autoInstrumentationImage.nodejs.repository }}:{{ .Values.manager.autoInstrumentationImage.nodejs.tag }} + {{- end }} + {{- if and .Values.manager.autoInstrumentationImage.python.repository .Values.manager.autoInstrumentationImage.python.tag }} + - --auto-instrumentation-python-image={{ .Values.manager.autoInstrumentationImage.python.repository }}:{{ .Values.manager.autoInstrumentationImage.python.tag }} + {{- end }} + {{- if and .Values.manager.autoInstrumentationImage.dotnet.repository .Values.manager.autoInstrumentationImage.dotnet.tag }} + - --auto-instrumentation-dotnet-image={{ .Values.manager.autoInstrumentationImage.dotnet.repository }}:{{ .Values.manager.autoInstrumentationImage.dotnet.tag }} + {{- end }} + {{- if and .Values.manager.autoInstrumentationImage.go.repository .Values.manager.autoInstrumentationImage.go.tag }} + - --auto-instrumentation-go-image={{ .Values.manager.autoInstrumentationImage.go.repository }}:{{ .Values.manager.autoInstrumentationImage.go.tag }} + {{- end }} + {{- if .Values.manager.featureGates }} + - --feature-gates={{ .Values.manager.featureGates }} + {{- end }} + {{- if .Values.manager.extraArgs }} + {{- .Values.manager.extraArgs | toYaml | nindent 12 }} + {{- end }} + command: + - /manager + {{- if .Values.manager.env }} + env: + {{- range $name, $value := .Values.manager.env }} + - name: {{ $name }} + value: {{ $value | quote -}} + {{- end }} + {{- end }} + image: "{{ .Values.manager.image.repository }}:{{ .Values.manager.image.tag }}" + name: manager + ports: + - containerPort: {{ .Values.manager.ports.metricsPort }} + name: metrics + protocol: TCP + {{- if or .Values.admissionWebhooks.create .Values.admissionWebhooks.secretName }} + - containerPort: {{ .Values.manager.ports.webhookPort }} + name: webhook-server + protocol: TCP + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: {{ .Values.manager.ports.healthzPort }} + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: {{ .Values.manager.ports.healthzPort }} + initialDelaySeconds: 5 + periodSeconds: 10 + resources: {{ toYaml .Values.manager.resources | nindent 12 }} + {{- if or .Values.admissionWebhooks.create .Values.admissionWebhooks.secretName }} + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + {{- end }} + {{- with .Values.manager.securityContext }} + securityContext: {{ toYaml . | nindent 12 }} + {{- end }} + {{ if .Values.kubeRBACProxy.enabled }} + - args: + - --secure-listen-address=0.0.0.0:{{ .Values.kubeRBACProxy.ports.proxyPort }} + - --upstream=http://127.0.0.1:{{ .Values.manager.ports.metricsPort }}/ + - --logtostderr=true + - --v=0 + {{- if .Values.kubeRBACProxy.extraArgs }} + {{- .Values.kubeRBACProxy.extraArgs | toYaml | nindent 12 }} + {{- end }} + image: "{{ .Values.kubeRBACProxy.image.repository }}:{{ .Values.kubeRBACProxy.image.tag }}" + name: kube-rbac-proxy + ports: + - containerPort: {{ .Values.kubeRBACProxy.ports.proxyPort }} + name: https + protocol: TCP + {{- with .Values.kubeRBACProxy.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.kubeRBACProxy.securityContext }} + securityContext: {{ toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{ toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "opentelemetry-operator.serviceAccountName" . }} + terminationGracePeriodSeconds: 10 + {{- if or .Values.admissionWebhooks.create .Values.admissionWebhooks.secretName }} + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: {{ default (printf "%s-controller-manager-service-cert" (include "opentelemetry-operator.fullname" .)) .Values.admissionWebhooks.secretName }} + {{- end }} + securityContext: +{{ toYaml .Values.securityContext | indent 8 }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/pdb.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/pdb.yaml new file mode 100644 index 00000000..77992304 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/pdb.yaml @@ -0,0 +1,21 @@ +{{- if .Values.pdb.create }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + {{- if .Values.pdb.minAvailable }} + minAvailable: {{ .Values.pdb.minAvailable }} + {{- end }} + {{- if .Values.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.pdb.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "opentelemetry-operator.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller-manager +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/prometheusrule.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/prometheusrule.yaml new file mode 100644 index 00000000..8f6b82d5 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/prometheusrule.yaml @@ -0,0 +1,42 @@ +{{- if and .Values.manager.prometheusRule.enabled .Values.manager.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "opentelemetry-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + {{- range $key, $value := .Values.manager.prometheusRule.extraLabels }} + {{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }} + {{- end }} + annotations: + {{- range $key, $value := .Values.manager.serviceMonitor.annotations }} + {{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }} + {{- end }} +spec: + groups: +{{- if .Values.manager.prometheusRule.groups }} + {{- toYaml .Values.manager.prometheusRule.groups | nindent 4 }} +{{- end }} +{{- if .Values.manager.prometheusRule.defaultRules.enabled }} + - name: managerRules + rules: + - alert: ReconcileErrors + expr: rate(controller_runtime_reconcile_total{controller="opentelemetrycollector",result="error"}[5m]) > 0 + for: 5m + labels: + severity: warning + annotations: + description: '{{`Reconciliation errors for {{ $labels.controller }} is increasing and has now reached {{ humanize $value }} `}}' + runbook_url: 'Check manager logs for reasons why this might happen' + - alert: WorkqueueDepth + expr: workqueue_depth{name="opentelemetrycollector"} > 0 + for: 5m + labels: + severity: warning + annotations: + description: '{{`Queue depth for {{ $labels.name }} has reached {{ $value }} `}}' + runbook_url: 'Check manager logs for reasons why this might happen' +{{- end }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/role.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/role.yaml new file mode 100644 index 00000000..73564ed7 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/role.yaml @@ -0,0 +1,38 @@ +{{- if and .Values.role.create .Values.manager.leaderElection.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }}-leader-election + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/rolebinding.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/rolebinding.yaml new file mode 100644 index 00000000..7064a176 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/rolebinding.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.role.create .Values.manager.leaderElection.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }}-leader-election + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "opentelemetry-operator.fullname" . }}-leader-election +subjects: + - kind: ServiceAccount + name: {{ template "opentelemetry-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/service.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/service.yaml new file mode 100644 index 00000000..e3b08c82 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/service.yaml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + ports: + {{- if .Values.kubeRBACProxy.enabled }} + - name: https + port: {{ .Values.kubeRBACProxy.ports.proxyPort }} + protocol: TCP + targetPort: https + {{- end }} + - name: metrics + port: {{ .Values.manager.ports.metricsPort }} + protocol: TCP + targetPort: metrics + selector: + {{- include "opentelemetry-operator.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller-manager + +{{- if or .Values.admissionWebhooks.create .Values.admissionWebhooks.secretName }} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + name: {{ template "opentelemetry-operator.fullname" . }}-webhook + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: 443 + protocol: TCP + targetPort: webhook-server + selector: + {{- include "opentelemetry-operator.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller-manager +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/serviceaccount.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/serviceaccount.yaml new file mode 100644 index 00000000..8300ba40 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if .Values.manager.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "opentelemetry-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + {{- if .Values.manager.serviceAccount.annotations }} + annotations: + {{- range $key, $value := .Values.manager.serviceAccount.annotations }} + {{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/servicemonitor.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/servicemonitor.yaml new file mode 100644 index 00000000..0633cf08 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/servicemonitor.yaml @@ -0,0 +1,29 @@ +{{- if .Values.manager.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "opentelemetry-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + {{- range $key, $value := .Values.manager.serviceMonitor.extraLabels }} + {{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }} + {{- end }} + {{- if .Values.manager.serviceMonitor.annotations }} + annotations: + {{- range $key, $value := .Values.manager.serviceMonitor.annotations }} + {{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }} + {{- end }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "opentelemetry-operator.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller-manager + endpoints: + {{- toYaml .Values.manager.serviceMonitor.metricsEndpoints | nindent 2 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/tests/test-certmanager-connection.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/tests/test-certmanager-connection.yaml new file mode 100644 index 00000000..f60b10f8 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/tests/test-certmanager-connection.yaml @@ -0,0 +1,42 @@ +{{- if and .Values.admissionWebhooks.create .Values.admissionWebhooks.certManager.enabled }} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "opentelemetry-operator.fullname" . }}-cert-manager" + namespace: {{ .Release.Namespace }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: webhook + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: "{{ .Values.testFramework.image.repository }}:{{ .Values.testFramework.image.tag }}" + env: + - name: CERT_MANAGER_CLUSTERIP + value: "cert-manager-webhook" + - name: CERT_MANAGER_PORT + value: "443" + command: + - sh + - -c + # The following shell script tests if the cert-manager service is up. If the service is up, when we try + # to wget its exposed port, we will get an HTTP error 400. + - | + wget_output=$(wget -q "$CERT_MANAGER_CLUSTERIP:$CERT_MANAGER_PORT") + if wget_output=="wget: server returned error: HTTP/1.0 400 Bad Request" + then exit 0 + else exit 1 + fi + restartPolicy: Never + {{- with .Values.affinity }} + affinity: {{ toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: {{ toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/tests/test-service-connection.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/tests/test-service-connection.yaml new file mode 100644 index 00000000..203eb432 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/tests/test-service-connection.yaml @@ -0,0 +1,85 @@ +{{ if .Values.kubeRBACProxy.enabled }} +--- +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "opentelemetry-operator.fullname" . }}-metrics" + namespace: {{ .Release.Namespace }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: "{{ .Values.testFramework.image.repository }}:{{ .Values.testFramework.image.tag }}" + env: + - name: MANAGER_METRICS_SERVICE_CLUSTERIP + value: "{{ include "opentelemetry-operator.fullname" . }}" + - name: MANAGER_METRICS_SERVICE_PORT + value: "{{ .Values.kubeRBACProxy.ports.proxyPort }}" + command: + - sh + - -c + # The following shell script tests if the controller-manager-metrics-service is up. + # If the service is up, when we try to wget its exposed port, we will get an HTTP error 400. + - | + wget_output=$(wget -q "$MANAGER_METRICS_SERVICE_CLUSTERIP:$MANAGER_METRICS_SERVICE_PORT") + if wget_output=="wget: server returned error: HTTP/1.0 400 Bad Request" + then exit 0 + else exit 1 + fi + restartPolicy: Never + {{- with .Values.affinity }} + affinity: {{ toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: {{ toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 4 }} + {{- end }} +{{- end }} +--- +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "opentelemetry-operator.fullname" . }}-webhook" + namespace: {{ .Release.Namespace }} + labels: + {{- include "opentelemetry-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: controller-manager + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: "{{ .Values.testFramework.image.repository }}:{{ .Values.testFramework.image.tag }}" + env: + - name: WEBHOOK_SERVICE_CLUSTERIP + value: "{{ include "opentelemetry-operator.fullname" . }}-webhook" + - name: WEBHOOK_SERVICE_PORT + value: "443" + command: + - sh + - -c + # The following shell script tests if the webhook service is up. If the service is up, when we try + # to wget its exposed port, we will get an HTTP error 400. + - | + wget_output=$(wget -q "$WEBHOOK_SERVICE_CLUSTERIP:$WEBHOOK_SERVICE_PORT") + if wget_output=="wget: server returned error: HTTP/1.0 400 Bad Request" + then exit 0 + else exit 1 + fi + restartPolicy: Never + {{- with .Values.affinity }} + affinity: {{ toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: {{ toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 4 }} + {{- end }} + diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/verticalpodautoscaler.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/verticalpodautoscaler.yaml new file mode 100644 index 00000000..660c535b --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/templates/verticalpodautoscaler.yaml @@ -0,0 +1,38 @@ +{{- if and (.Capabilities.APIVersions.Has "autoscaling.k8s.io/v1") (.Values.manager.verticalPodAutoscaler.enabled) }} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{ template "opentelemetry-operator.fullname" . }}-operator + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "opentelemetry-operator.name" . }}-operator +{{- include "opentelemetry-operator.labels" . | nindent 4 }} +spec: + resourcePolicy: + containerPolicies: + - containerName: manager + {{- if .Values.manager.verticalPodAutoscaler.controlledResources }} + controlledResources: {{ .Values.manager.verticalPodAutoscaler.controlledResources }} + {{- end }} + {{- if .Values.manager.verticalPodAutoscaler.maxAllowed }} + maxAllowed: + {{- toYaml .Values.manager.verticalPodAutoscaler.maxAllowed | nindent 8 }} + {{- end }} + {{- if .Values.manager.verticalPodAutoscaler.minAllowed }} + minAllowed: + {{- toYaml .Values.manager.verticalPodAutoscaler.minAllowed | nindent 8 }} + {{- end }} + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ template "opentelemetry-operator.fullname" . }} + {{- if .Values.manager.verticalPodAutoscaler.updatePolicy }} + updatePolicy: + {{- if .Values.manager.verticalPodAutoscaler.updatePolicy.updateMode }} + updateMode: {{ .Values.manager.verticalPodAutoscaler.updatePolicy.updateMode }} + {{- end }} + {{- if .Values.manager.verticalPodAutoscaler.updatePolicy.minReplicas }} + minReplicas: {{ .Values.manager.verticalPodAutoscaler.updatePolicy.minReplicas }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/values.schema.json b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/values.schema.json new file mode 100644 index 00000000..4a027209 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/values.schema.json @@ -0,0 +1,1852 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "http://example.com/example.json", + "type": "object", + "default": {}, + "title": "Root Schema", + "required": [ + "replicaCount", + "nameOverride", + "imagePullSecrets", + "pdb", + "manager", + "kubeRBACProxy", + "admissionWebhooks", + "role", + "clusterRole", + "affinity", + "tolerations", + "nodeSelector", + "topologySpreadConstraints", + "hostNetwork", + "priorityClassName", + "securityContext", + "testFramework" + ], + "properties": { + "replicaCount": { + "type": "integer", + "default": 0, + "title": "The replicaCount Schema", + "examples": [ + 1 + ] + }, + "nameOverride": { + "type": "string", + "default": "", + "title": "The nameOverride Schema", + "examples": [ + "" + ] + }, + "imagePullSecrets": { + "type": "array", + "default": [], + "title": "The imagePullSecrets Schema", + "items": {}, + "examples": [ + [] + ] + }, + "pdb": { + "type": "object", + "default": {}, + "title": "The pdb Schema", + "required": [ + "create", + "minAvailable", + "maxUnavailable" + ], + "properties": { + "create": { + "type": "boolean", + "default": false, + "title": "The create Schema", + "examples": [ + false + ] + }, + "minAvailable": { + "oneOf": [ + { + "type": ["string", "null"] + }, + { + "type": ["integer", "null"] + } + ] + }, + "maxUnavailable": { + "oneOf": [ + { + "type": ["string", "null"] + }, + { + "type": ["integer", "null"] + } + ] + } + }, + "examples": [{ + "create": false, + "minAvailable": 1, + "maxUnavailable": "" + }] + }, + "manager": { + "type": "object", + "default": {}, + "title": "The manager Schema", + "required": [ + "image", + "collectorImage", + "opampBridgeImage", + "targetAllocatorImage", + "autoInstrumentationImage", + "featureGates", + "ports", + "resources", + "env", + "serviceAccount", + "serviceMonitor", + "podAnnotations", + "podLabels", + "prometheusRule", + "extraArgs", + "leaderElection", + "verticalPodAutoscaler", + "rolling", + "securityContext" + ], + "properties": { + "image": { + "type": "object", + "default": {}, + "title": "The image Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "ghcr.io/open-telemetry/opentelemetry-operator/opentelemetry-operator" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "v0.89.0" + ] + } + }, + "examples": [{ + "repository": "ghcr.io/open-telemetry/opentelemetry-operator/opentelemetry-operator", + "tag": "v0.89.0" + }] + }, + "collectorImage": { + "type": "object", + "default": {}, + "title": "The collectorImage Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "otel/opentelemetry-collector-contrib" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "0.89.0" + ] + } + }, + "examples": [{ + "repository": "otel/opentelemetry-collector-contrib", + "tag": "0.89.0" + }] + }, + "opampBridgeImage": { + "type": "object", + "default": {}, + "title": "The opampBridgeImage Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "" + ] + } + }, + "examples": [{ + "repository": "", + "tag": "" + }] + }, + "targetAllocatorImage": { + "type": "object", + "default": {}, + "title": "The targetAllocatorImage Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "" + ] + } + }, + "examples": [{ + "repository": "", + "tag": "" + }] + }, + "autoInstrumentationImage": { + "type": "object", + "default": {}, + "title": "The autoInstrumentationImage Schema", + "required": [ + "java", + "nodejs", + "python", + "dotnet", + "go" + ], + "properties": { + "java": { + "type": "object", + "default": {}, + "title": "The java Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "" + ] + } + }, + "examples": [{ + "repository": "", + "tag": "" + }] + }, + "nodejs": { + "type": "object", + "default": {}, + "title": "The nodejs Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "" + ] + } + }, + "examples": [{ + "repository": "", + "tag": "" + }] + }, + "python": { + "type": "object", + "default": {}, + "title": "The python Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "" + ] + } + }, + "examples": [{ + "repository": "", + "tag": "" + }] + }, + "dotnet": { + "type": "object", + "default": {}, + "title": "The dotnet Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "" + ] + } + }, + "examples": [{ + "repository": "", + "tag": "" + }] + }, + "go": { + "type": "object", + "default": {}, + "title": "The go Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "" + ] + } + }, + "examples": [{ + "repository": "", + "tag": "" + }] + } + }, + "examples": [{ + "java": { + "repository": "", + "tag": "" + }, + "nodejs": { + "repository": "", + "tag": "" + }, + "python": { + "repository": "", + "tag": "" + }, + "dotnet": { + "repository": "", + "tag": "" + }, + "go": { + "repository": "", + "tag": "" + } + }] + }, + "featureGates": { + "type": "string", + "default": "", + "title": "The featureGates Schema", + "examples": [ + "" + ] + }, + "ports": { + "type": "object", + "default": {}, + "title": "The ports Schema", + "required": [ + "metricsPort", + "webhookPort", + "healthzPort" + ], + "properties": { + "metricsPort": { + "type": "integer", + "default": 0, + "title": "The metricsPort Schema", + "examples": [ + 8080 + ] + }, + "webhookPort": { + "type": "integer", + "default": 0, + "title": "The webhookPort Schema", + "examples": [ + 9443 + ] + }, + "healthzPort": { + "type": "integer", + "default": 0, + "title": "The healthzPort Schema", + "examples": [ + 8081 + ] + } + }, + "examples": [{ + "metricsPort": 8080, + "webhookPort": 9443, + "healthzPort": 8081 + }] + }, + "resources": { + "type": "object", + "default": {}, + "title": "The resources Schema", + "required": [ + "limits", + "requests" + ], + "properties": { + "limits": { + "type": "object", + "default": {}, + "title": "The limits Schema", + "required": [ + "cpu", + "memory" + ], + "properties": { + "cpu": { + "type": "string", + "default": "", + "title": "The cpu Schema", + "examples": [ + "100m" + ] + }, + "memory": { + "type": "string", + "default": "", + "title": "The memory Schema", + "examples": [ + "128Mi" + ] + } + }, + "examples": [{ + "cpu": "100m", + "memory": "128Mi" + }] + }, + "requests": { + "type": "object", + "default": {}, + "title": "The requests Schema", + "required": [ + "cpu", + "memory" + ], + "properties": { + "cpu": { + "type": "string", + "default": "", + "title": "The cpu Schema", + "examples": [ + "100m" + ] + }, + "memory": { + "type": "string", + "default": "", + "title": "The memory Schema", + "examples": [ + "64Mi" + ] + } + }, + "examples": [{ + "cpu": "100m", + "memory": "64Mi" + }] + } + }, + "examples": [{ + "limits": { + "cpu": "100m", + "memory": "128Mi" + }, + "requests": { + "cpu": "100m", + "memory": "64Mi" + } + }] + }, + "env": { + "type": "object", + "default": {}, + "title": "The env Schema", + "required": [ + "ENABLE_WEBHOOKS" + ], + "properties": { + "ENABLE_WEBHOOKS": { + "type": "string", + "default": "", + "title": "The ENABLE_WEBHOOKS Schema", + "examples": [ + "true" + ] + } + }, + "examples": [{ + "ENABLE_WEBHOOKS": "true" + }] + }, + "serviceAccount": { + "type": "object", + "default": {}, + "title": "The serviceAccount Schema", + "required": [ + "create", + "annotations" + ], + "properties": { + "create": { + "type": "boolean", + "default": false, + "title": "The create Schema", + "examples": [ + true + ] + }, + "annotations": { + "type": "object", + "default": {}, + "title": "The annotations Schema", + "required": [], + "properties": {}, + "examples": [{}] + } + }, + "examples": [{ + "create": true, + "annotations": {} + }] + }, + "serviceMonitor": { + "type": "object", + "default": {}, + "title": "The serviceMonitor Schema", + "required": [ + "enabled", + "extraLabels", + "annotations", + "metricsEndpoints" + ], + "properties": { + "enabled": { + "type": "boolean", + "default": false, + "title": "The enabled Schema", + "examples": [ + false + ] + }, + "extraLabels": { + "type": "object", + "default": {}, + "title": "The extraLabels Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "annotations": { + "type": "object", + "default": {}, + "title": "The annotations Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "metricsEndpoints": { + "type": "array", + "default": [], + "title": "The metricsEndpoints Schema", + "items": { + "type": "object", + "default": {}, + "title": "A Schema", + "required": [ + "port" + ], + "properties": { + "port": { + "type": "string", + "default": "", + "title": "The port Schema", + "examples": [ + "metrics" + ] + } + }, + "examples": [{ + "port": "metrics" + }] + }, + "examples": [ + [{ + "port": "metrics" + }] + ] + } + }, + "examples": [{ + "enabled": false, + "extraLabels": {}, + "annotations": {}, + "metricsEndpoints": [{ + "port": "metrics" + }] + }] + }, + "podAnnotations": { + "type": "object", + "default": {}, + "title": "The podAnnotations Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "podLabels": { + "type": "object", + "default": {}, + "title": "The podLabels Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "prometheusRule": { + "type": "object", + "default": {}, + "title": "The prometheusRule Schema", + "required": [ + "enabled", + "groups", + "defaultRules", + "extraLabels", + "annotations" + ], + "properties": { + "enabled": { + "type": "boolean", + "default": false, + "title": "The enabled Schema", + "examples": [ + false + ] + }, + "groups": { + "type": "array", + "default": [], + "title": "The groups Schema", + "items": {}, + "examples": [ + [] + ] + }, + "defaultRules": { + "type": "object", + "default": {}, + "title": "The defaultRules Schema", + "required": [ + "enabled" + ], + "properties": { + "enabled": { + "type": "boolean", + "default": false, + "title": "The enabled Schema", + "examples": [ + false + ] + } + }, + "examples": [{ + "enabled": false + }] + }, + "extraLabels": { + "type": "object", + "default": {}, + "title": "The extraLabels Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "annotations": { + "type": "object", + "default": {}, + "title": "The annotations Schema", + "required": [], + "properties": {}, + "examples": [{}] + } + }, + "examples": [{ + "enabled": false, + "groups": [], + "defaultRules": { + "enabled": false + }, + "extraLabels": {}, + "annotations": {} + }] + }, + "extraArgs": { + "type": "array", + "default": [], + "title": "The extraArgs Schema", + "items": {}, + "examples": [ + [] + ] + }, + "leaderElection": { + "type": "object", + "default": {}, + "title": "The leaderElection Schema", + "required": [ + "enabled" + ], + "properties": { + "enabled": { + "type": "boolean", + "default": false, + "title": "The enabled Schema", + "examples": [ + true + ] + } + }, + "examples": [{ + "enabled": true + }] + }, + "verticalPodAutoscaler": { + "type": "object", + "default": {}, + "title": "The verticalPodAutoscaler Schema", + "required": [ + "enabled", + "controlledResources", + "maxAllowed", + "minAllowed", + "updatePolicy" + ], + "properties": { + "enabled": { + "type": "boolean", + "default": false, + "title": "The enabled Schema", + "examples": [ + false + ] + }, + "controlledResources": { + "type": "array", + "default": [], + "title": "The controlledResources Schema", + "items": {}, + "examples": [ + [] + ] + }, + "maxAllowed": { + "type": "object", + "default": {}, + "title": "The maxAllowed Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "minAllowed": { + "type": "object", + "default": {}, + "title": "The minAllowed Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "updatePolicy": { + "type": "object", + "default": {}, + "title": "The updatePolicy Schema", + "required": [ + "updateMode", + "minReplicas" + ], + "properties": { + "updateMode": { + "type": "string", + "default": "", + "title": "The updateMode Schema", + "examples": [ + "Auto" + ] + }, + "minReplicas": { + "type": "integer", + "default": 0, + "title": "The minReplicas Schema", + "examples": [ + 2 + ] + } + }, + "examples": [{ + "updateMode": "Auto", + "minReplicas": 2 + }] + } + }, + "examples": [{ + "enabled": false, + "controlledResources": [], + "maxAllowed": {}, + "minAllowed": {}, + "updatePolicy": { + "updateMode": "Auto", + "minReplicas": 2 + } + }] + }, + "rolling": { + "type": "boolean", + "default": false, + "title": "The rolling Schema", + "examples": [ + false + ] + }, + "securityContext": { + "type": "object", + "default": {}, + "title": "The securityContext Schema", + "required": [], + "properties": {}, + "examples": [{}] + } + }, + "examples": [{ + "image": { + "repository": "ghcr.io/open-telemetry/opentelemetry-operator/opentelemetry-operator", + "tag": "v0.89.0" + }, + "collectorImage": { + "repository": "otel/opentelemetry-collector-contrib", + "tag": "0.89.0" + }, + "opampBridgeImage": { + "repository": "", + "tag": "" + }, + "targetAllocatorImage": { + "repository": "", + "tag": "" + }, + "autoInstrumentationImage": { + "java": { + "repository": "", + "tag": "" + }, + "nodejs": { + "repository": "", + "tag": "" + }, + "python": { + "repository": "", + "tag": "" + }, + "dotnet": { + "repository": "", + "tag": "" + }, + "go": { + "repository": "", + "tag": "" + } + }, + "featureGates": "", + "ports": { + "metricsPort": 8080, + "webhookPort": 9443, + "healthzPort": 8081 + }, + "resources": { + "limits": { + "cpu": "100m", + "memory": "128Mi" + }, + "requests": { + "cpu": "100m", + "memory": "64Mi" + } + }, + "env": { + "ENABLE_WEBHOOKS": "true" + }, + "serviceAccount": { + "create": true, + "annotations": {} + }, + "serviceMonitor": { + "enabled": false, + "extraLabels": {}, + "annotations": {}, + "metricsEndpoints": [{ + "port": "metrics" + }] + }, + "podAnnotations": {}, + "podLabels": {}, + "prometheusRule": { + "enabled": false, + "groups": [], + "defaultRules": { + "enabled": false + }, + "extraLabels": {}, + "annotations": {} + }, + "extraArgs": [], + "leaderElection": { + "enabled": true + }, + "verticalPodAutoscaler": { + "enabled": false, + "controlledResources": [], + "maxAllowed": {}, + "minAllowed": {}, + "updatePolicy": { + "updateMode": "Auto", + "minReplicas": 2 + } + }, + "rolling": false, + "securityContext": {} + }] + }, + "kubeRBACProxy": { + "type": "object", + "default": {}, + "title": "The kubeRBACProxy Schema", + "required": [ + "enabled", + "image", + "ports", + "resources", + "extraArgs", + "securityContext" + ], + "properties": { + "enabled": { + "type": "boolean", + "default": false, + "title": "The enabled Schema", + "examples": [ + true + ] + }, + "image": { + "type": "object", + "default": {}, + "title": "The image Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "quay.io/brancz/kube-rbac-proxy" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "v0.15.0" + ] + } + }, + "examples": [{ + "repository": "quay.io/brancz/kube-rbac-proxy", + "tag": "v0.15.0" + }] + }, + "ports": { + "type": "object", + "default": {}, + "title": "The ports Schema", + "required": [ + "proxyPort" + ], + "properties": { + "proxyPort": { + "type": "integer", + "default": 0, + "title": "The proxyPort Schema", + "examples": [ + 8443 + ] + } + }, + "examples": [{ + "proxyPort": 8443 + }] + }, + "resources": { + "type": "object", + "default": {}, + "title": "The resources Schema", + "required": [ + "limits", + "requests" + ], + "properties": { + "limits": { + "type": "object", + "default": {}, + "title": "The limits Schema", + "required": [ + "cpu", + "memory" + ], + "properties": { + "cpu": { + "type": "string", + "default": "", + "title": "The cpu Schema", + "examples": [ + "500m" + ] + }, + "memory": { + "type": "string", + "default": "", + "title": "The memory Schema", + "examples": [ + "128Mi" + ] + } + }, + "examples": [{ + "cpu": "500m", + "memory": "128Mi" + }] + }, + "requests": { + "type": "object", + "default": {}, + "title": "The requests Schema", + "required": [ + "cpu", + "memory" + ], + "properties": { + "cpu": { + "type": "string", + "default": "", + "title": "The cpu Schema", + "examples": [ + "5m" + ] + }, + "memory": { + "type": "string", + "default": "", + "title": "The memory Schema", + "examples": [ + "64Mi" + ] + } + }, + "examples": [{ + "cpu": "5m", + "memory": "64Mi" + }] + } + }, + "examples": [{ + "limits": { + "cpu": "500m", + "memory": "128Mi" + }, + "requests": { + "cpu": "5m", + "memory": "64Mi" + } + }] + }, + "extraArgs": { + "type": "array", + "default": [], + "title": "The extraArgs Schema", + "items": {}, + "examples": [ + [] + ] + }, + "securityContext": { + "type": "object", + "default": {}, + "title": "The securityContext Schema", + "required": [], + "properties": {}, + "examples": [{}] + } + }, + "examples": [{ + "enabled": true, + "image": { + "repository": "quay.io/brancz/kube-rbac-proxy", + "tag": "v0.15.0" + }, + "ports": { + "proxyPort": 8443 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "128Mi" + }, + "requests": { + "cpu": "5m", + "memory": "64Mi" + } + }, + "extraArgs": [], + "securityContext": {} + }] + }, + "admissionWebhooks": { + "type": "object", + "default": {}, + "title": "The admissionWebhooks Schema", + "required": [ + "create", + "failurePolicy", + "secretName", + "pods", + "namePrefix", + "timeoutSeconds", + "namespaceSelector", + "objectSelector", + "certManager", + "autoGenerateCert", + "cert_file", + "key_file", + "ca_file", + "secretAnnotations", + "secretLabels" + ], + "properties": { + "create": { + "type": "boolean", + "default": false, + "title": "The create Schema", + "examples": [ + true + ] + }, + "failurePolicy": { + "type": "string", + "default": "", + "title": "The failurePolicy Schema", + "examples": [ + "Fail" + ] + }, + "secretName": { + "type": "string", + "default": "", + "title": "The secretName Schema", + "examples": [ + "" + ] + }, + "pods": { + "type": "object", + "default": {}, + "title": "The pods Schema", + "required": [ + "failurePolicy" + ], + "properties": { + "failurePolicy": { + "type": "string", + "default": "", + "title": "The failurePolicy Schema", + "examples": [ + "Ignore" + ] + } + }, + "examples": [{ + "failurePolicy": "Ignore" + }] + }, + "namePrefix": { + "type": "string", + "default": "", + "title": "The namePrefix Schema", + "examples": [ + "" + ] + }, + "timeoutSeconds": { + "type": "integer", + "default": 0, + "title": "The timeoutSeconds Schema", + "examples": [ + 10 + ] + }, + "namespaceSelector": { + "type": "object", + "default": {}, + "title": "The namespaceSelector Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "objectSelector": { + "type": "object", + "default": {}, + "title": "The objectSelector Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "enablePodOperationsWebhook": { + "type": "boolean", + "default": true, + "title": "deploy pod operations webhook", + "required": [], + "properties": {}, + "examples": [false] + }, + "certManager": { + "type": "object", + "default": {}, + "title": "The certManager Schema", + "required": [ + "enabled", + "issuerRef", + "certificateAnnotations", + "issuerAnnotations" + ], + "properties": { + "enabled": { + "type": "boolean", + "default": false, + "title": "The enabled Schema", + "examples": [ + true + ] + }, + "issuerRef": { + "type": "object", + "default": {}, + "title": "The issuerRef Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "certificateAnnotations": { + "type": "object", + "default": {}, + "title": "The certificateAnnotations Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "issuerAnnotations": { + "type": "object", + "default": {}, + "title": "The issuerAnnotations Schema", + "required": [], + "properties": {}, + "examples": [{}] + } + }, + "examples": [{ + "enabled": true, + "issuerRef": {}, + "certificateAnnotations": {}, + "issuerAnnotations": {} + }] + }, + "autoGenerateCert": { + "type": "object", + "default": {}, + "title": "The autoGenerateCert Schema", + "required": [ + "enabled", + "recreate" + ], + "properties": { + "enabled": { + "type": "boolean", + "default": false, + "title": "The enabled Schema", + "examples": [ + true + ] + }, + "recreate": { + "type": "boolean", + "default": false, + "title": "The recreate Schema", + "examples": [ + true + ] + } + }, + "examples": [{ + "enabled": true, + "recreate": true + }] + }, + "cert_file": { + "type": "string", + "default": "", + "title": "The cert_file Schema", + "examples": [ + "" + ] + }, + "key_file": { + "type": "string", + "default": "", + "title": "The key_file Schema", + "examples": [ + "" + ] + }, + "ca_file": { + "type": "string", + "default": "", + "title": "The ca_file Schema", + "examples": [ + "" + ] + }, + "secretAnnotations": { + "type": "object", + "default": {}, + "title": "The secretAnnotations Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "secretLabels": { + "type": "object", + "default": {}, + "title": "The secretLabels Schema", + "required": [], + "properties": {}, + "examples": [{}] + } + }, + "examples": [{ + "create": true, + "failurePolicy": "Fail", + "secretName": "", + "pods": { + "failurePolicy": "Ignore" + }, + "namePrefix": "", + "timeoutSeconds": 10, + "namespaceSelector": {}, + "objectSelector": {}, + "certManager": { + "enabled": true, + "issuerRef": {}, + "certificateAnnotations": {}, + "issuerAnnotations": {} + }, + "autoGenerateCert": { + "enabled": true, + "recreate": true + }, + "cert_file": "", + "key_file": "", + "ca_file": "", + "secretAnnotations": {}, + "secretLabels": {} + }] + }, + "role": { + "type": "object", + "default": {}, + "title": "The role Schema", + "required": [ + "create" + ], + "properties": { + "create": { + "type": "boolean", + "default": false, + "title": "The create Schema", + "examples": [ + true + ] + } + }, + "examples": [{ + "create": true + }] + }, + "clusterRole": { + "type": "object", + "default": {}, + "title": "The clusterRole Schema", + "required": [ + "create" + ], + "properties": { + "create": { + "type": "boolean", + "default": false, + "title": "The create Schema", + "examples": [ + true + ] + } + }, + "examples": [{ + "create": true + }] + }, + "affinity": { + "type": "object", + "default": {}, + "title": "The affinity Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "tolerations": { + "type": "array", + "default": [], + "title": "The tolerations Schema", + "items": {}, + "examples": [ + [] + ] + }, + "nodeSelector": { + "type": "object", + "default": {}, + "title": "The nodeSelector Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, + "topologySpreadConstraints": { + "type": "array", + "default": [], + "title": "The topologySpreadConstraints Schema", + "items": {}, + "examples": [ + [] + ] + }, + "hostNetwork": { + "type": "boolean", + "default": false, + "title": "The hostNetwork Schema", + "examples": [ + false + ] + }, + "priorityClassName": { + "type": "string", + "default": "", + "title": "The priorityClassName Schema", + "examples": [ + "" + ] + }, + "securityContext": { + "type": "object", + "default": {}, + "title": "The securityContext Schema", + "required": [ + "runAsGroup", + "runAsNonRoot", + "runAsUser", + "fsGroup" + ], + "properties": { + "runAsGroup": { + "type": "integer", + "default": 0, + "title": "The runAsGroup Schema", + "examples": [ + 65532 + ] + }, + "runAsNonRoot": { + "type": "boolean", + "default": false, + "title": "The runAsNonRoot Schema", + "examples": [ + true + ] + }, + "runAsUser": { + "type": "integer", + "default": 0, + "title": "The runAsUser Schema", + "examples": [ + 65532 + ] + }, + "fsGroup": { + "type": "integer", + "default": 0, + "title": "The fsGroup Schema", + "examples": [ + 65532 + ] + } + }, + "examples": [{ + "runAsGroup": 65532, + "runAsNonRoot": true, + "runAsUser": 65532, + "fsGroup": 65532 + }] + }, + "testFramework": { + "type": "object", + "default": {}, + "title": "The testFramework Schema", + "required": [ + "image" + ], + "properties": { + "image": { + "type": "object", + "default": {}, + "title": "The image Schema", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "type": "string", + "default": "", + "title": "The repository Schema", + "examples": [ + "busybox" + ] + }, + "tag": { + "type": "string", + "default": "", + "title": "The tag Schema", + "examples": [ + "latest" + ] + } + }, + "examples": [{ + "repository": "busybox", + "tag": "latest" + }] + } + }, + "examples": [{ + "image": { + "repository": "busybox", + "tag": "latest" + } + }] + } + }, + "examples": [{ + "replicaCount": 1, + "nameOverride": "", + "imagePullSecrets": [], + "pdb": { + "create": false, + "minAvailable": 1, + "maxUnavailable": "" + }, + "manager": { + "image": { + "repository": "ghcr.io/open-telemetry/opentelemetry-operator/opentelemetry-operator", + "tag": "v0.89.0" + }, + "collectorImage": { + "repository": "otel/opentelemetry-collector-contrib", + "tag": "0.89.0" + }, + "opampBridgeImage": { + "repository": "", + "tag": "" + }, + "targetAllocatorImage": { + "repository": "", + "tag": "" + }, + "autoInstrumentationImage": { + "java": { + "repository": "", + "tag": "" + }, + "nodejs": { + "repository": "", + "tag": "" + }, + "python": { + "repository": "", + "tag": "" + }, + "dotnet": { + "repository": "", + "tag": "" + }, + "go": { + "repository": "", + "tag": "" + } + }, + "featureGates": "", + "ports": { + "metricsPort": 8080, + "webhookPort": 9443, + "healthzPort": 8081 + }, + "resources": { + "limits": { + "cpu": "100m", + "memory": "128Mi" + }, + "requests": { + "cpu": "100m", + "memory": "64Mi" + } + }, + "env": { + "ENABLE_WEBHOOKS": "true" + }, + "serviceAccount": { + "create": true, + "annotations": {} + }, + "serviceMonitor": { + "enabled": false, + "extraLabels": {}, + "annotations": {}, + "metricsEndpoints": [{ + "port": "metrics" + }] + }, + "podAnnotations": {}, + "podLabels": {}, + "prometheusRule": { + "enabled": false, + "groups": [], + "defaultRules": { + "enabled": false + }, + "extraLabels": {}, + "annotations": {} + }, + "extraArgs": [], + "leaderElection": { + "enabled": true + }, + "verticalPodAutoscaler": { + "enabled": false, + "controlledResources": [], + "maxAllowed": {}, + "minAllowed": {}, + "updatePolicy": { + "updateMode": "Auto", + "minReplicas": 2 + } + }, + "rolling": false, + "securityContext": {} + }, + "kubeRBACProxy": { + "enabled": true, + "image": { + "repository": "quay.io/brancz/kube-rbac-proxy", + "tag": "v0.15.0" + }, + "ports": { + "proxyPort": 8443 + }, + "resources": { + "limits": { + "cpu": "500m", + "memory": "128Mi" + }, + "requests": { + "cpu": "5m", + "memory": "64Mi" + } + }, + "extraArgs": [], + "securityContext": {} + }, + "admissionWebhooks": { + "create": true, + "failurePolicy": "Fail", + "secretName": "", + "pods": { + "failurePolicy": "Ignore" + }, + "namePrefix": "", + "timeoutSeconds": 10, + "namespaceSelector": {}, + "objectSelector": {}, + "certManager": { + "enabled": true, + "issuerRef": {}, + "certificateAnnotations": {}, + "issuerAnnotations": {} + }, + "autoGenerateCert": { + "enabled": true, + "recreate": true + }, + "cert_file": "", + "key_file": "", + "ca_file": "", + "secretAnnotations": {}, + "secretLabels": {} + }, + "role": { + "create": true + }, + "clusterRole": { + "create": true + }, + "affinity": {}, + "tolerations": [], + "nodeSelector": {}, + "topologySpreadConstraints": [], + "hostNetwork": false, + "priorityClassName": "", + "securityContext": { + "runAsGroup": 65532, + "runAsNonRoot": true, + "runAsUser": 65532, + "fsGroup": 65532 + }, + "testFramework": { + "image": { + "repository": "busybox", + "tag": "latest" + } + } + }] +} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/values.yaml new file mode 100644 index 00000000..79630c47 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/charts/opentelemetry-operator/values.yaml @@ -0,0 +1,274 @@ +# Default values for opentelemetry-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +## Provide a name in place of opentelemetry-operator. +## +nameOverride: "" + +## Reference one or more secrets to be used when pulling images from authenticated repositories. +imagePullSecrets: [] + +## Pod Disruption Budget configuration +## +pdb: + ## Enable/disable a Pod Disruption Budget creation + ## + create: false + ## Minimum number/percentage of pods that should remain scheduled + ## + minAvailable: 1 + ## Maximum number/percentage of pods that may be made unavailable + ## + maxUnavailable: "" + +## Provide OpenTelemetry Operator manager container image and resources. +## +manager: + image: + repository: ghcr.io/open-telemetry/opentelemetry-operator/opentelemetry-operator + tag: v0.89.0 + collectorImage: + repository: otel/opentelemetry-collector-contrib + tag: 0.89.0 + opampBridgeImage: + repository: "" + tag: "" + targetAllocatorImage: + repository: "" + tag: "" + autoInstrumentationImage: + java: + repository: "" + tag: "" + nodejs: + repository: "" + tag: "" + python: + repository: "" + tag: "" + dotnet: + repository: "" + tag: "" + # The Go instrumentaiton support in the operator is disabled by default. + # To enable it, use the operator.autoinstrumentation.go feature gate. + go: + repository: "" + tag: "" + # Feature Gates are a a comma-delimited list of feature gate identifiers. + # Prefix a gate with '-' to disable support. + # Prefixing a gate with '+' or no prefix will enable support. + # A full list of valud identifiers can be found here: https://github.com/open-telemetry/opentelemetry-operator/blob/main/pkg/featuregate/featuregate.go + featureGates: "" + ports: + metricsPort: 8080 + webhookPort: 9443 + healthzPort: 8081 + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 64Mi + ## Adds additional environment variables + ## e.g ENV_VAR: env_value + env: + ENABLE_WEBHOOKS: "true" + + # -- Create the manager ServiceAccount + serviceAccount: + create: true + annotations: {} + # name: nameOverride + + ## Enable ServiceMonitor for Prometheus metrics scrape + serviceMonitor: + enabled: false + # additional labels on the ServiceMonitor + extraLabels: {} + # add annotations on the ServiceMonitor + annotations: {} + metricsEndpoints: + - port: metrics + + podAnnotations: {} + podLabels: {} + + prometheusRule: + enabled: false + groups: [] + # Create default rules for monitoring the manager + defaultRules: + enabled: false + # additional labels on the PrometheusRule + extraLabels: {} + # add annotations on the PrometheusRule + annotations: {} + + + ## List of additional cli arguments to configure the manager + ## for example: --labels, etc. + extraArgs: [] + + ## Enable leader election mechanism for protecting against split brain if multiple operator pods/replicas are started. + ## See more at https://docs.openshift.com/container-platform/4.10/operators/operator_sdk/osdk-leader-election.html + leaderElection: + enabled: true + + # Enable vertical pod autoscaler support for the manager + verticalPodAutoscaler: + enabled: false + # List of resources that the vertical pod autoscaler can control. Defaults to cpu and memory + controlledResources: [] + + # Define the max allowed resources for the pod + maxAllowed: {} + # cpu: 200m + # memory: 100Mi + # Define the min allowed resources for the pod + minAllowed: {} + # cpu: 200m + # memory: 100Mi + + updatePolicy: + # Specifies whether recommended updates are applied when a Pod is started and whether recommended updates + # are applied during the life of a Pod. Possible values are "Off", "Initial", "Recreate", and "Auto". + updateMode: Auto + # Minimal number of replicas which need to be alive for Updater to attempt pod eviction. + # Only positive values are allowed. The default is 2. + minReplicas: 2 + # Enable manager pod automatically rolling + rolling: false + + ## Container specific securityContext + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + securityContext: {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + +## Provide OpenTelemetry Operator kube-rbac-proxy container image. +## +kubeRBACProxy: + enabled: true + image: + repository: quay.io/brancz/kube-rbac-proxy + tag: v0.15.0 + ports: + proxyPort: 8443 + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 5m + memory: 64Mi + + ## List of additional cli arguments to configure the kube-rbac-proxy + ## for example: --tls-cipher-suites, --tls-min-version, etc. + extraArgs: [] + + ## Container specific securityContext + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + securityContext: {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + +## Admission webhooks make sure only requests with correctly formatted rules will get into the Operator. +## They also enable the sidecar injection for OpenTelemetryCollector and Instrumentation CR's +admissionWebhooks: + create: true + failurePolicy: Fail + enablePodOperationsWebhook: true + secretName: "" + + ## Defines the sidecar injection logic in Pods. + ## - Ignore, the injection is fail-open. The pod will be created, but the sidecar won't be injected. + ## - Fail, the injection is fail-close. If the webhook pod is not ready, pods cannot be created. + pods: + failurePolicy: Ignore + + ## Adds a prefix to the mutating webook name. + ## This can be used to order this mutating webhook with all your cluster's mutating webhooks. + namePrefix: "" + + ## Customize webhook timeout duration + timeoutSeconds: 10 + + ## Provide selectors for your objects + namespaceSelector: {} + objectSelector: {} + + ## https://github.com/open-telemetry/opentelemetry-helm-charts/blob/main/charts/opentelemetry-operator/README.md#tls-certificate-requirement + ## TLS Certificate Option 1: Use certManager to generate self-signed certificate. + ## certManager must be enabled. If enabled, always takes precendence over options 2 and 3. + certManager: + enabled: true + ## Provide the issuer kind and name to do the cert auth job. + ## By default, OpenTelemetry Operator will use self-signer issuer. + issuerRef: {} + # kind: + # name: + ## Annotations for the cert and issuer if cert-manager is enabled. + certificateAnnotations: {} + issuerAnnotations: {} + + ## TLS Certificate Option 2: Use Helm to automatically generate self-signed certificate. + ## certManager must be disabled and autoGenerateCert must be enabled. + ## If true and certManager.enabled is false, Helm will automatically create a self-signd cert and secret for you. + autoGenerateCert: + enabled: true + # If set to true, new webhook key/certificate is generated on helm upgrade. + recreate: true + + ## TLS Certificate Option 3: Use your own self-signed certificate. + ## certManager and autoGenerateCert must be disabled and cert_file, key_file, and ca_file must be set. + ## Path to your own PEM-encoded certificate. + cert_file: "" + ## Path to your own PEM-encoded private key. + key_file: "" + ## Path to the CA cert. + ca_file: "" + + ## Secret annotations + secretAnnotations: {} + ## Secret labels + secretLabels: {} + +## Create the provided Roles and RoleBindings +## +role: + create: true + +## Create the provided ClusterRoles and ClusterRoleBindings +## +clusterRole: + create: true + +affinity: {} +tolerations: [] +nodeSelector: {} +topologySpreadConstraints: [] +hostNetwork: false + +# Allows for pod scheduler prioritisation +priorityClassName: "" + +## SecurityContext holds pod-level security attributes and common container settings. +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +securityContext: + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + fsGroup: 65532 + +testFramework: + image: + repository: busybox + tag: latest diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/NOTES.txt b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/NOTES.txt new file mode 100644 index 00000000..14027b56 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/NOTES.txt @@ -0,0 +1,31 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +The chart installs the following components + +1) OpenTelemetry Operator + Enabled: {{ index .Values "opentelemetry-operator" "enabled"}} + +2) AppDynamics Cloud Operator + Enabled: {{ index .Values "appdynamics-cloud-operator" "enabled" }} + Description: Uses custom resources to manage the life cycle of Cluster Collector, Infrastructure Collector and Log Collector. + +3) FSO Agent Management Orchestration Client + Enabled: {{ index .Values "appdynamics-smartagent" "enabled" }} + Description: Performs and manages operations of collector agents in a couple of ways + 1. create, update and delete agents provided in orchestration client config, it can work with multiple agents + 2. manages configuration by fetching it from the fso management solution and passing down to collector agents + +THIRD PARTY LICENSE DISCLOSURE +=============================== + +AppDynamics Cloud Operator +-------------------------------------------------- +https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/AppDynamics_Cloud_Operator-2440-1713560401.pdf + +AppDynamics Cloud FSO Agent Management +-------------------------------------------------- +https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/AppDynamics_Cloud_FSO_Agent_management-2440-1713932409.pdf diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/_helpers.tpl b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/_helpers.tpl new file mode 100644 index 00000000..01f6fed4 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "appdynamics-operators.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "appdynamics-operators.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "appdynamics-operators.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "appdynamics-operators.labels" -}} +helm.sh/chart: {{ include "appdynamics-operators.chart" . }} +{{ include "appdynamics-operators.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "appdynamics-operators.selectorLabels" -}} +app.kubernetes.io/name: {{ include "appdynamics-operators.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "appdynamics-operators.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "appdynamics-operators.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/opentelemetry_operator_openshift_scc.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/opentelemetry_operator_openshift_scc.yaml new file mode 100644 index 00000000..c562c0be --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/templates/opentelemetry_operator_openshift_scc.yaml @@ -0,0 +1,22 @@ +{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1/SecurityContextConstraints" -}} +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + annotations: + kubernetes.io/description: 'opentelemetry-operator-privileged-scc is a custom SCC for OpenTelemetry Operator' + name: opentelemetry-operator-privileged-scc + namespace: {{ .Release.Namespace }} +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegedContainer: false +readOnlyRootFilesystem: true +runAsUser: + type: MustRunAsNonRoot +seLinuxContext: + type: MustRunAs +users: +- system:serviceaccount:{{ .Release.Namespace }}:{{index .Values "opentelemetry-operator" "manager" "serviceAccount" "name" | required "Service account name for Opentelemetry Operator manager is required" }} +{{- end }} \ No newline at end of file diff --git a/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/values.yaml b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/values.yaml new file mode 100644 index 00000000..9f5bc159 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/charts/appdynamics-operators/values.yaml @@ -0,0 +1,25 @@ +appdynamics-cloud-operator: + enabled: true + operatorPod: + image: appdynamics/appdynamics-cloud-operator:24.4.0-1445 + imagePullPolicy: Always + imagePullSecrets: [] + nodeSelector: + kubernetes.io/os: linux + kubeRbacProxy: {} + +opentelemetry-operator: + enabled: true + nodeSelector: + kubernetes.io/os: linux + manager: + serviceAccount: + name: opentelemetry-operator + +appdynamics-smartagent: + enabled: true + # Manually setting the operator helm chart version. + # Temp fix until the smartagent is installed via the operator helm chart. + # Ultimately, customer will install only the smartagent helm chart. + # Operator helm chart will be installed via the smartagent (with Agent Mgmt UI). + helmChartVersion: 1.21.0 diff --git a/packs/appdynamics-operators-1.21.368/logo.png b/packs/appdynamics-operators-1.21.368/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1d1df3101d6e82c90297ee170e5affb460fa04cf GIT binary patch literal 47881 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 XLAmJpoR(>C00000NkvXXu0mjfwk`lp literal 0 HcmV?d00001 diff --git a/packs/appdynamics-operators-1.21.368/pack.json b/packs/appdynamics-operators-1.21.368/pack.json new file mode 100644 index 00000000..b771cdb9 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/pack.json @@ -0,0 +1,18 @@ +{ + "addonType": "monitoring", + "annotations": { + "ingressSupported": "false", + "source": "community", + "contributor": "appdynamics" + }, + "cloudTypes": [ + "all" + ], + "charts": [ + "charts/appdynamics-operators-1.21.368.tgz" + ], + "displayName": "Cisco AppDynamics Operators", + "layer": "addon", + "name": "cisco-appdynamics-operators", + "version": "1.21.368" +} diff --git a/packs/appdynamics-operators-1.21.368/values.yaml b/packs/appdynamics-operators-1.21.368/values.yaml new file mode 100644 index 00000000..bc3e0582 --- /dev/null +++ b/packs/appdynamics-operators-1.21.368/values.yaml @@ -0,0 +1,37 @@ +pack: + namespace: "appdynamics" + releaseNameOverride: + appdynamics-operators: operator + content: + images: + - image: appdynamics/appdynamics-cloud-operator:24.4.0-1445 + charts: + - repo: https://appdynamics.jfrog.io/artifactory/appdynamics-cloud-helmcharts/ + name: appdynamics-operators + version: 1.21.368 +charts: + appdynamics-operators: + global: + clusterName: + appdynamics-cloud-operator: + operatorPod: + image: appdynamics/appdynamics-cloud-operator:24.4.0-1445 + imagePullPolicy: Always + imagePullSecrets: [] + nodeSelector: + kubernetes.io/os: linux + kubeRbacProxy: {} + opentelemetry-operator: + nodeSelector: + kubernetes.io/os: linux + manager: + serviceAccount: + name: opentelemetry-operator + appdynamics-smartagent: + solution: + endpoint: + oauth: + clientId: + clientSecret: + tokenUrl: + tenantId: From 63afe2a1d5cbb58ee2a349ba319e5167b369f06c Mon Sep 17 00:00:00 2001 From: Appdynamics Release Management Date: Thu, 2 May 2024 11:29:20 +0000 Subject: [PATCH 11/22] AppD charts appdynamics-collectors 1.21.1264 --- .../README.md | 26 + .../appdynamics-collectors-1.21.1264.tgz | Bin 0 -> 156160 bytes .../charts/appdynamics-collectors/.helmignore | 25 + .../charts/appdynamics-collectors/Chart.lock | 27 + .../charts/appdynamics-collectors/Chart.yaml | 50 + .../charts/appdynamics-collectors/LICENSE | 11 + .../Chart.yaml | 18 + .../README.md | 32 + .../templates/_helper.tpl | 3 + .../templates/auto-instrumentation-agent.yaml | 174 ++ .../rbac/cr-agent-instrumentation.yaml | 63 + .../rbac/crb-agent-instrumentation.yaml | 14 + .../templates/rbac/sa-agent.yaml | 5 + .../secret-auto-instrumentation-agent.yaml | 23 + .../templates/secrets/secret-custom-ssl.yaml | 22 + .../secrets/secret-proxy-secret.yaml | 25 + .../values.yaml | 48 + .../.helmignore | 23 + .../appdynamics-cloud-db-collector/Chart.yaml | 19 + .../templates/_helper.tpl | 36 + .../templates/dbCollector.yaml | 56 + .../templates/dbConfig.yaml | 61 + .../templates/dbConfigDbPasswordSecrets.yaml | 24 + .../rbac/dbcollector_openshift_scc.yaml | 24 + .../rbac/dbcollector_service_account.yaml | 7 + .../values.schema.json | 415 +++++ .../values.yaml | 78 + .../.helmignore | 23 + .../Chart.yaml | 18 + .../templates/_helper.tpl | 561 ++++++ .../templates/clustermon.yaml | 107 ++ .../templates/containermon.yaml | 46 + .../templates/inframon.yaml | 107 ++ .../templates/logCollector.yaml | 87 + .../rbac/clustermon_clusterrole.yaml | 73 + .../rbac/clustermon_clusterrole_binding.yaml | 14 + .../rbac/clustermon_openshift_scc.yaml | 24 + .../rbac/clustermon_service_account.yaml | 7 + .../templates/rbac/inframon_clusterrole.yaml | 22 + .../rbac/inframon_clusterrole_binding.yaml | 14 + .../rbac/inframon_openshift_scc.yaml | 24 + .../rbac/inframon_service_account.yaml | 7 + .../rbac/logcollector_clusterrole.yaml | 33 + .../logcollector_clusterrole_binding.yaml | 14 + .../rbac/logcollector_openshift_scc.yaml | 32 + .../rbac/logcollector_service_account.yaml | 7 + .../templates/servermon.yaml | 61 + .../values.schema.json | 1499 +++++++++++++++++ .../values.yaml | 254 +++ .../.helmignore | 25 + .../Chart.lock | 6 + .../Chart.yaml | 25 + .../README.md | 37 + .../charts/metrics-server/.helmignore | 23 + .../charts/metrics-server/Chart.yaml | 26 + .../charts/metrics-server/README.md | 64 + .../charts/metrics-server/ci/ci-values.yaml | 2 + .../charts/metrics-server/templates/NOTES.txt | 7 + .../metrics-server/templates/_helpers.tpl | 78 + .../metrics-server/templates/apiservice.yaml | 17 + .../clusterrole-aggregated-reader.yaml | 21 + .../metrics-server/templates/clusterrole.yaml | 32 + .../clusterrolebinding-auth-delegator.yaml | 16 + .../templates/clusterrolebinding.yaml | 16 + .../metrics-server/templates/deployment.yaml | 94 ++ .../charts/metrics-server/templates/pdb.yaml | 18 + .../charts/metrics-server/templates/psp.yaml | 28 + .../metrics-server/templates/rolebinding.yaml | 17 + .../metrics-server/templates/service.yaml | 22 + .../templates/serviceaccount.yaml | 12 + .../charts/metrics-server/values.yaml | 121 ++ .../templates/NOTES.txt | 15 + .../templates/_helper.tpl | 5 + .../templates/cluster-agent.yaml | 228 +++ .../templates/infraviz.yaml | 120 ++ .../templates/rbac/cr-agent-generic.yaml | 73 + .../rbac/cr-agent-instrumentation.yaml | 66 + .../templates/rbac/crb-agent-generic.yaml | 16 + .../rbac/crb-agent-instrumentation.yaml | 16 + ...security-context-constraint-openshift.yaml | 35 + .../templates/rbac/sa-agent.yaml | 9 + .../templates/rbac/sa-infraviz.yaml | 7 + .../templates/secret-cluster-agent.yaml | 27 + .../templates/secret-custom-ssl.yaml | 22 + .../templates/secret-proxy-secret.yaml | 25 + .../values.yaml | 136 ++ .../appdynamics-network-monitoring/Chart.yaml | 8 + .../templates/_helpers.tpl | 66 + .../templates/k8s-collector-clusterrole.yaml | 34 + .../k8s-collector-clusterrolebinding.yaml | 17 + .../templates/k8s-collector-deployment.yaml | 81 + .../k8s-collector-serviceaccount.yaml | 9 + .../templates/kernel-collector-daemonset.yaml | 92 + .../kernel-collector-serviceaccount.yaml | 9 + .../templates/reducer-deployment.yaml | 82 + .../templates/reducer-service.yaml | 22 + .../values.schema.json | 155 ++ .../values.yaml | 80 + .../appdynamics-otel-collector/Chart.yaml | 8 + .../appdynamics-otel-collector/README.md | 71 + .../examples/client_secret_env.yaml | 8 + .../examples/headless_service.yaml | 10 + .../examples/instrumentation.yaml | 12 + .../examples/instrumentation_tls.yaml | 33 + .../examples/not_installed.yaml | 2 + .../examples/prometheus.yaml | 11 + .../examples/prometheus_and_filelog.yaml | 19 + .../examples/remove_oauth.yaml | 17 + .../examples/self_telemetry.yaml | 11 + .../examples/simple.yaml | 11 + .../examples/tailsampling.yaml | 62 + .../examples/tls_from_secret_exporter.yaml | 20 + .../examples/tls_from_secret_receiver.yaml | 19 + .../examples/tls_values.yaml | 23 + .../templates/NOTES.txt | 28 + .../_agent_management_and_global_input.tpl | 107 ++ .../templates/_config-sampler.tpl | 152 ++ .../templates/_helps.tpl | 238 +++ .../templates/_release-specific.tpl | 7 + .../templates/_spec-daemonset.tpl | 186 ++ .../templates/_spec-linux.tpl | 67 + .../templates/_spec-sidecar.tpl | 74 + .../templates/_spec-statefulset.tpl | 140 ++ .../templates/_spec-tailsampler.tpl | 84 + .../templates/_spec-windows.tpl | 67 + .../templates/_spec.tpl | 652 +++++++ .../opentelemetry-collector-daemonset.yaml | 43 + .../opentelemetry-collector-sidecar.yaml | 35 + .../opentelemetry-collector-statefulset.yaml | 43 + .../opentelemetry-collector-tailsampler.yaml | 43 + .../templates/rbac.yaml | 33 + .../templates/service-account.yaml | 19 + .../templates/service.yaml | 129 ++ .../templates/target-allocator-rbac.yaml | 39 + .../target-allocator-service-account.yaml | 17 + .../templates/tests/simple-test-loadgen.yaml | 20 + .../values.schema.json | 696 ++++++++ .../appdynamics-otel-collector/values.yaml | 522 ++++++ .../.helmignore | 23 + .../Chart.yaml | 6 + .../examples/defaults.yaml | 2 + .../examples/oob.yaml | 9 + .../templates/Instrumentation.yaml | 36 + .../_agent_management_and_global_input.tpl | 15 + .../values.schema.json | 76 + .../values.yaml | 31 + .../appdynamics-security-collector/Chart.yaml | 15 + .../charts/panoptica/.helmignore | 27 + .../charts/panoptica/Chart.yaml | 12 + .../charts/panoptica/README.md | 249 +++ .../panoptica/charts/postgresql/.helmignore | 21 + .../panoptica/charts/postgresql/Chart.yaml | 30 + .../panoptica/charts/postgresql/README.md | 672 ++++++++ .../postgresql/charts/common/.helmignore | 22 + .../postgresql/charts/common/Chart.yaml | 23 + .../charts/postgresql/charts/common/README.md | 350 ++++ .../charts/common/templates/_affinities.tpl | 102 ++ .../charts/common/templates/_capabilities.tpl | 154 ++ .../charts/common/templates/_errors.tpl | 23 + .../charts/common/templates/_images.tpl | 75 + .../charts/common/templates/_ingress.tpl | 68 + .../charts/common/templates/_labels.tpl | 18 + .../charts/common/templates/_names.tpl | 70 + .../charts/common/templates/_secrets.tpl | 140 ++ .../charts/common/templates/_storage.tpl | 23 + .../charts/common/templates/_tplvalues.tpl | 13 + .../charts/common/templates/_utils.tpl | 62 + .../charts/common/templates/_warnings.tpl | 14 + .../templates/validations/_cassandra.tpl | 72 + .../common/templates/validations/_mariadb.tpl | 103 ++ .../common/templates/validations/_mongodb.tpl | 108 ++ .../common/templates/validations/_mysql.tpl | 103 ++ .../templates/validations/_postgresql.tpl | 129 ++ .../common/templates/validations/_redis.tpl | 76 + .../templates/validations/_validations.tpl | 46 + .../postgresql/charts/common/values.yaml | 5 + .../charts/postgresql/templates/NOTES.txt | 89 + .../charts/postgresql/templates/_helpers.tpl | 382 +++++ .../postgresql/templates/extra-list.yaml | 4 + .../templates/networkpolicy-egress.yaml | 32 + .../templates/primary/configmap.yaml | 24 + .../templates/primary/extended-configmap.yaml | 18 + .../primary/initialization-configmap.yaml | 15 + .../templates/primary/metrics-configmap.yaml | 16 + .../templates/primary/metrics-svc.yaml | 31 + .../templates/primary/networkpolicy.yaml | 57 + .../templates/primary/servicemonitor.yaml | 48 + .../templates/primary/statefulset.yaml | 642 +++++++ .../templates/primary/svc-headless.yaml | 31 + .../postgresql/templates/primary/svc.yaml | 51 + .../postgresql/templates/prometheusrule.yaml | 22 + .../charts/postgresql/templates/psp.yaml | 41 + .../templates/read/metrics-configmap.yaml | 16 + .../templates/read/metrics-svc.yaml | 31 + .../templates/read/networkpolicy.yaml | 36 + .../templates/read/servicemonitor.yaml | 48 + .../templates/read/statefulset.yaml | 523 ++++++ .../templates/read/svc-headless.yaml | 33 + .../charts/postgresql/templates/read/svc.yaml | 53 + .../charts/postgresql/templates/role.yaml | 31 + .../postgresql/templates/rolebinding.yaml | 22 + .../charts/postgresql/templates/secrets.yaml | 29 + .../postgresql/templates/serviceaccount.yaml | 19 + .../postgresql/templates/tls-secrets.yaml | 27 + .../charts/postgresql/values.schema.json | 156 ++ .../panoptica/charts/postgresql/values.yaml | 1374 +++++++++++++++ .../charts/panoptica/templates/_helpers.tpl | 43 + .../templates/apiclarity/_helpers.tpl | 44 + .../templates/apiclarity/clusterrole.yaml | 19 + .../apiclarity/clusterrolebinding.yaml | 17 + .../templates/apiclarity/deployment.yaml | 165 ++ .../apiclarity/fuzzer-template-configmap.yaml | 67 + .../headers-to-ignore-configmap.yaml | 117 ++ .../panoptica/templates/apiclarity/pvc.yaml | 22 + .../panoptica/templates/apiclarity/role.yaml | 18 + .../templates/apiclarity/rolebinding.yaml | 17 + .../templates/apiclarity/secret.yaml | 11 + .../templates/apiclarity/service-lb.yaml | 18 + .../templates/apiclarity/service.yaml | 41 + .../templates/apiclarity/serviceaccount.yaml | 13 + .../panoptica/templates/apiclarity/tls.yaml | 71 + .../apiclarity/wasm-envoy-filter.yaml | 150 ++ .../templates/controller/_helpers.tpl | 59 + ...s-docker-benchmark-template-configmap.yaml | 75 + .../cluster-configuration-configmap.yaml | 100 ++ .../templates/controller/clusterrole.yaml | 90 + .../controller/clusterrolebinding.yaml | 14 + .../templates/controller/deployment.yaml | 265 +++ .../panoptica/templates/controller/hpa.yaml | 33 + .../image-analysis-clusterrole.yaml | 18 + .../image-analysis-clusterrolebinding.yaml | 14 + .../image-analysis-template-configmap.yaml | 93 + .../k8s-cis-benchmark-clusterrole.yaml | 13 + .../k8s-cis-benchmark-clusterrolebinding.yaml | 16 + .../controller/k8s-cis-benchmark-role.yaml | 19 + .../k8s-cis-benchmark-rolebinding.yaml | 17 + .../k8s-cis-benchmark-template-configmap.yaml | 80 + .../controller/k8s-discovery-clusterrole.yaml | 73 + .../k8s-discovery-clusterrolebinding.yaml | 14 + .../controller/kafka-authz-configmap.yaml | 12 + .../controller/kafka-injector-configmap.yaml | 25 + .../mutatingwebhookconfiguration.yaml | 104 ++ .../panoptica/templates/controller/pdb.yaml | 19 + .../templates/controller/post-delete-job.yaml | 104 ++ .../panoptica/templates/controller/pvc.yaml | 26 + .../panoptica/templates/controller/role.yaml | 16 + .../templates/controller/rolebinding.yaml | 15 + .../templates/controller/secret.yaml | 12 + .../templates/controller/service.yaml | 82 + .../templates/controller/serviceaccount.yaml | 13 + .../sidecar-injector-configmap.yaml | 58 + .../validatingwebhookconfiguration.yaml | 156 ++ .../templates/istio/destinationrule.yaml | 16 + .../templates/istio/extauth_1.10.yaml | 385 +++++ .../templates/istio/extauth_1.11.yaml | 385 +++++ .../templates/istio/extauth_1.12.yaml | 385 +++++ .../templates/istio/extauth_1.13.yaml | 385 +++++ .../templates/istio/extauth_1.14.yaml | 385 +++++ .../templates/istio/extauth_1.15.yaml | 385 +++++ .../templates/istio/extauth_1.16.yaml | 385 +++++ .../templates/istio/extauth_1.17.yaml | 385 +++++ .../templates/istio/extauth_1.18.yaml | 385 +++++ .../templates/istio/extauth_1.19.yaml | 385 +++++ .../templates/istio/extauth_1.9.yaml | 385 +++++ .../templates/istio/passthrough_1.10.yaml | 36 + .../templates/istio/passthrough_1.11.yaml | 36 + .../templates/istio/passthrough_1.12.yaml | 36 + .../templates/istio/passthrough_1.13.yaml | 36 + .../templates/istio/passthrough_1.14.yaml | 36 + .../templates/istio/passthrough_1.15.yaml | 36 + .../templates/istio/passthrough_1.16.yaml | 36 + .../templates/istio/passthrough_1.17.yaml | 36 + .../templates/istio/passthrough_1.18.yaml | 36 + .../templates/istio/passthrough_1.19.yaml | 36 + .../templates/istio/passthrough_1.9.yaml | 36 + .../panoptica/templates/istio/peerauth.yaml | 10 + .../templates/istio/post-delete-job.yaml | 153 ++ .../panoptica/templates/istio/sidecar.yaml | 13 + .../templates/istio/stackdriver_1.10.yaml | 81 + .../templates/istio/stackdriver_1.11.yaml | 81 + .../templates/istio/stackdriver_1.12.yaml | 81 + .../templates/istio/stackdriver_1.13.yaml | 83 + .../templates/istio/stackdriver_1.14.yaml | 83 + .../templates/istio/stackdriver_1.15.yaml | 83 + .../templates/istio/stackdriver_1.16.yaml | 83 + .../templates/istio/stackdriver_1.17.yaml | 83 + .../templates/istio/stackdriver_1.18.yaml | 83 + .../templates/istio/stackdriver_1.19.yaml | 83 + .../templates/istio/stackdriver_1.9.yaml | 81 + .../templates/seccomp-installer/_helpers.tpl | 45 + .../seccomp-installer/serviceaccount.yaml | 13 + .../upgrader/clusterrolebinding.yaml | 16 + .../templates/upgrader/serviceaccount.yaml | 9 + .../upgrader/upgrader-template-configmap.yaml | 72 + .../charts/panoptica/values.yaml | 516 ++++++ .../templates/NOTES.txt | 5 + .../templates/_helpers.tpl | 63 + .../values.yaml | 7 + .../ci/appdynamics-collectors-values.yaml | 8 + .../examples/certs.yaml | 59 + .../lca-sample-configs/complex-and-or.yaml | 43 + .../examples/lca-sample-configs/complex.yaml | 333 ++++ .../lca-sample-configs/minimal-config.yaml | 27 + .../minimal-default-config.yaml | 34 + .../lca-sample-configs/subparser-config.yaml | 38 + .../lca-sample-configs/troubleshooting.yaml | 63 + .../examples/logging.yaml | 13 + .../appdynamics-collectors/examples/mtls.yaml | 36 + .../examples/security-only.yaml | 18 + .../examples/simple-windows.yaml | 10 + .../examples/simple.yaml | 8 + .../appdynamics-collectors/examples/tls.yaml | 34 + .../examples/tls_exporter.yaml | 20 + .../templates/NOTES.txt | 63 + .../templates/_helpers.tpl | 71 + .../charts/appdynamics-collectors/values.yaml | 97 ++ .../appdynamics-collectors-1.21.1264/logo.png | Bin 0 -> 47881 bytes .../pack.json | 29 + .../values.yaml | 100 ++ 319 files changed, 27253 insertions(+) create mode 100644 packs/appdynamics-collectors-1.21.1264/README.md create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors-1.21.1264.tgz create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/.helmignore create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/Chart.lock create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/LICENSE create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/README.md create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/_helper.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/auto-instrumentation-agent.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/cr-agent-instrumentation.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/crb-agent-instrumentation.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/rbac/sa-agent.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-auto-instrumentation-agent.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-custom-ssl.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/templates/secrets/secret-proxy-secret.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-auto-instrumentation-agent/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/.helmignore create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/_helper.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbCollector.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbConfig.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/dbConfigDbPasswordSecrets.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/rbac/dbcollector_openshift_scc.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/templates/rbac/dbcollector_service_account.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/values.schema.json create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-db-collector/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/.helmignore create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/_helper.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/clustermon.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/containermon.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/inframon.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/logCollector.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_clusterrole.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_clusterrole_binding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_openshift_scc.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/clustermon_service_account.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_clusterrole.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_clusterrole_binding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_openshift_scc.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/inframon_service_account.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_clusterrole.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_clusterrole_binding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_openshift_scc.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/rbac/logcollector_service_account.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/templates/servermon.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/values.schema.json create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-cloud-k8s-monitoring/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/.helmignore create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/Chart.lock create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/README.md create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/.helmignore create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/README.md create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/ci/ci-values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/NOTES.txt create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/_helpers.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/apiservice.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrole-aggregated-reader.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrole.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrolebinding-auth-delegator.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/clusterrolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/deployment.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/pdb.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/psp.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/rolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/service.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/templates/serviceaccount.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/charts/metrics-server/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/NOTES.txt create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/_helper.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/cluster-agent.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/infraviz.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/cr-agent-generic.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/cr-agent-instrumentation.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/crb-agent-generic.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/crb-agent-instrumentation.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/infraviz-security-context-constraint-openshift.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/sa-agent.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/rbac/sa-infraviz.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-cluster-agent.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-custom-ssl.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/templates/secret-proxy-secret.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-csaas-k8s-cluster-agent/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/_helpers.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-clusterrole.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-clusterrolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-deployment.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/k8s-collector-serviceaccount.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/kernel-collector-daemonset.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/kernel-collector-serviceaccount.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/reducer-deployment.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/templates/reducer-service.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/values.schema.json create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-network-monitoring/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/README.md create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/client_secret_env.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/headless_service.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/instrumentation.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/instrumentation_tls.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/not_installed.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/prometheus.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/prometheus_and_filelog.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/remove_oauth.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/self_telemetry.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/simple.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tailsampling.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_from_secret_exporter.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_from_secret_receiver.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/examples/tls_values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/NOTES.txt create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_agent_management_and_global_input.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_config-sampler.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_helps.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_release-specific.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-daemonset.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-linux.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-sidecar.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-statefulset.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-tailsampler.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec-windows.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/_spec.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-daemonset.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-sidecar.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-statefulset.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/opentelemetry-collector-tailsampler.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/rbac.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/service-account.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/service.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/target-allocator-rbac.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/target-allocator-service-account.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/templates/tests/simple-test-loadgen.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/values.schema.json create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-collector/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/.helmignore create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/examples/defaults.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/examples/oob.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/templates/Instrumentation.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/templates/_agent_management_and_global_input.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/values.schema.json create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-otel-instrumentation/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/.helmignore create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/README.md create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/.helmignore create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/README.md create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/.helmignore create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/Chart.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/README.md create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_affinities.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_capabilities.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_errors.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_images.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_ingress.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_labels.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_names.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_secrets.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_storage.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_tplvalues.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_utils.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/_warnings.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_cassandra.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mariadb.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mongodb.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_mysql.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_postgresql.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_redis.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/templates/validations/_validations.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/charts/common/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/NOTES.txt create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/_helpers.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/extra-list.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/networkpolicy-egress.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/extended-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/initialization-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/metrics-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/metrics-svc.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/networkpolicy.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/servicemonitor.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/statefulset.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/svc-headless.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/primary/svc.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/prometheusrule.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/psp.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/metrics-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/metrics-svc.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/networkpolicy.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/servicemonitor.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/statefulset.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/svc-headless.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/read/svc.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/role.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/rolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/secrets.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/serviceaccount.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/templates/tls-secrets.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/values.schema.json create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/charts/postgresql/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/_helpers.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/_helpers.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/clusterrole.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/clusterrolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/deployment.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/fuzzer-template-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/headers-to-ignore-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/pvc.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/role.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/rolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/secret.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/service-lb.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/service.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/serviceaccount.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/tls.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/apiclarity/wasm-envoy-filter.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/_helpers.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/cis-docker-benchmark-template-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/cluster-configuration-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/clusterrole.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/clusterrolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/deployment.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/hpa.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-clusterrole.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-clusterrolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/image-analysis-template-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-clusterrole.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-clusterrolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-role.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-rolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-cis-benchmark-template-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-discovery-clusterrole.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/k8s-discovery-clusterrolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/kafka-authz-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/kafka-injector-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/mutatingwebhookconfiguration.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/pdb.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/post-delete-job.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/pvc.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/role.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/rolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/secret.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/service.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/serviceaccount.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/sidecar-injector-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/controller/validatingwebhookconfiguration.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/destinationrule.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.10.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.11.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.12.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.13.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.14.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.15.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.16.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.17.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.18.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.19.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/extauth_1.9.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.10.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.11.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.12.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.13.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.14.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.15.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.16.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.17.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.18.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.19.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/passthrough_1.9.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/peerauth.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/post-delete-job.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/sidecar.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.10.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.11.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.12.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.13.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.14.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.15.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.16.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.17.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.18.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.19.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/istio/stackdriver_1.9.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/seccomp-installer/_helpers.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/seccomp-installer/serviceaccount.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/clusterrolebinding.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/serviceaccount.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/templates/upgrader/upgrader-template-configmap.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/charts/panoptica/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/templates/NOTES.txt create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/templates/_helpers.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/charts/appdynamics-security-collector/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/ci/appdynamics-collectors-values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/certs.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/complex-and-or.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/complex.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/minimal-config.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/minimal-default-config.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/subparser-config.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/lca-sample-configs/troubleshooting.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/logging.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/mtls.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/security-only.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/simple-windows.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/simple.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/tls.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/examples/tls_exporter.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/templates/NOTES.txt create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/templates/_helpers.tpl create mode 100644 packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors/values.yaml create mode 100644 packs/appdynamics-collectors-1.21.1264/logo.png create mode 100644 packs/appdynamics-collectors-1.21.1264/pack.json create mode 100644 packs/appdynamics-collectors-1.21.1264/values.yaml diff --git a/packs/appdynamics-collectors-1.21.1264/README.md b/packs/appdynamics-collectors-1.21.1264/README.md new file mode 100644 index 00000000..f3019e92 --- /dev/null +++ b/packs/appdynamics-collectors-1.21.1264/README.md @@ -0,0 +1,26 @@ +## The Appdynamics Collector Cloud Helm Charts +An Add-on pack for Spectro Cloud to use the monitoring of k8s cluster with AppDynamics collectors. + +## Appdynamics Cloud Helm Charts +This repository maintains helm charts for installing Appdynamics Cloud Collector. + +## Parameters +| Parameter | Description | +|-----------|-------------| +| clusterName | String to specify the name of the k8s cluster | +| endpoint | The endpoint Tenant to which you want to send the data to. Please refer the product guide link from References for more details | +| clientId | clientId of your Tenant . Please refer the product guide link from References for more details | +| clientSecret | clientSecret of your Tenant. Please refer the product guide link from References for more details | +| tokenUrl | tokenUrl of your Tenant. Please refer the product guide link from References for more details | +| tenantId | tenantId of your Tenant. Please refer the product guide link from References for more details | + + +## References +To enable log collection for your cluster, please refer: +https://docs.appdynamics.com/fso/cloud-native-app-obs/en/kubernetes-and-app-service-monitoring/log-collection/onboard-logs-from-kubernetes/configure-the-log-collector + +Here is the guide to auto-instrument your application. +https://docs.appdynamics.com/fso/cloud-native-app-obs/en/kubernetes-and-app-service-monitoring/application-performance-monitoring-with-opentelemetry/configure-services-running-inside-a-supported-kubernetes-cluster/auto-instrument-your-services-using-opentelemetry-operator-for-kubernetes + +Here is the complete product guide about the AppDynamics collectors. +https://docs.appdynamics.com/fso/cloud-native-app-obs/en/kubernetes-and-app-service-monitoring/install-kubernetes-and-app-service-monitoring diff --git a/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors-1.21.1264.tgz b/packs/appdynamics-collectors-1.21.1264/charts/appdynamics-collectors-1.21.1264.tgz new file mode 100644 index 0000000000000000000000000000000000000000..3d7106b3d3a25ef170a4d8fbbf2c87e1ea9e9b12 GIT binary patch literal 156160 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