From fbc8cbe17429b3ab760a89db35f6928ad80100aa Mon Sep 17 00:00:00 2001 From: Kishor Joshi Date: Thu, 15 Oct 2020 17:47:09 -0700 Subject: [PATCH] Installation guide (#1509) * installation guide * controller configuration options * subnet auto-discovery * update configuration guide * Add documentation from the v1 release * reformat installation guide * reword IAM permissions section --- CONTRIBUTING.md | 23 ++ LICENSE | 202 ++++++++++ SECURITY_CONTACTS | 14 + code-of-conduct.md | 3 + docs/CONTRIBUTING.md | 1 + docs/assets/images/controller-design.png | Bin 0 -> 75747 bytes docs/assets/images/subnet-tags.png | Bin 0 -> 38974 bytes docs/code-of-conduct.md | 1 + docs/examples/2048/2048-deployment.yaml | 21 + docs/examples/2048/2048-ingress.yaml | 18 + docs/examples/2048/2048-namespace.yaml | 4 + docs/examples/2048/2048-service.yaml | 13 + docs/examples/cognito-ingress-template.yaml | 67 ++++ .../echoservice/echoserver-deployment.yaml | 21 + .../echoservice/echoserver-ingress.yaml | 18 + .../echoservice/echoserver-namespace.yaml | 4 + .../echoservice/echoserver-service.yaml | 13 + docs/examples/external-dns.yaml | 64 ++++ docs/guide/controller/configurations.md | 94 ++++- docs/guide/controller/how-it-works.md | 44 +++ docs/guide/controller/installation.md | 70 +++- docs/guide/controller/subnet_discovery.md | 31 +- docs/guide/ingress/spec.md | 31 ++ docs/guide/integrations/external_dns.md | 68 +++- docs/guide/tasks/cognito_authentication.md | 29 +- docs/guide/tasks/migrate_legacy_apps.md | 42 ++ docs/guide/tasks/ssl_redirect.md | 47 ++- docs/guide/walkthrough/echo_server.md | 359 +++++++++++++++++- 28 files changed, 1295 insertions(+), 7 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 SECURITY_CONTACTS create mode 100644 code-of-conduct.md create mode 120000 docs/CONTRIBUTING.md create mode 100644 docs/assets/images/controller-design.png create mode 100755 docs/assets/images/subnet-tags.png create mode 120000 docs/code-of-conduct.md create mode 100644 docs/examples/2048/2048-deployment.yaml create mode 100644 docs/examples/2048/2048-ingress.yaml create mode 100644 docs/examples/2048/2048-namespace.yaml create mode 100644 docs/examples/2048/2048-service.yaml create mode 100644 docs/examples/cognito-ingress-template.yaml create mode 100644 docs/examples/echoservice/echoserver-deployment.yaml create mode 100644 docs/examples/echoservice/echoserver-ingress.yaml create mode 100644 docs/examples/echoservice/echoserver-namespace.yaml create mode 100644 docs/examples/echoservice/echoserver-service.yaml create mode 100644 docs/examples/external-dns.yaml create mode 100644 docs/guide/controller/how-it-works.md create mode 100644 docs/guide/ingress/spec.md create mode 100644 docs/guide/tasks/migrate_legacy_apps.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..b6aae447c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# Contributing Guidelines + +Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://github.com/kubernetes/community)! The Kubernetes community abides by the CNCF [code of conduct](code-of-conduct.md). Here is an excerpt: + +_As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._ + +## Getting Started + +[`BUILDING.md`](/docs/BUILDING.md) has instructions on how to build the project. +We also have more documentation on how to get started contributing here: + +- [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests +- [Kubernetes Contributor Guide](http://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](http://git.k8s.io/community/contributors/guide#contributing) +- [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet.md) - Common resources for existing developers + +## Mentorship + +- [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers! + +## Contact Information + +- [Slack channel](https://kubernetes.slack.com/messages/sig-aws) +- [Mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-aws) diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + 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. diff --git a/SECURITY_CONTACTS b/SECURITY_CONTACTS new file mode 100644 index 000000000..3f73dedfb --- /dev/null +++ b/SECURITY_CONTACTS @@ -0,0 +1,14 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Team to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +bigkraig +M00nF1sh diff --git a/code-of-conduct.md b/code-of-conduct.md new file mode 100644 index 000000000..0d15c00cf --- /dev/null +++ b/code-of-conduct.md @@ -0,0 +1,3 @@ +# Kubernetes Community Code of Conduct + +Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 120000 index 000000000..44fcc6343 --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1 @@ +../CONTRIBUTING.md \ No newline at end of file diff --git a/docs/assets/images/controller-design.png b/docs/assets/images/controller-design.png new file mode 100644 index 0000000000000000000000000000000000000000..020e9a9ff26008ff4c701ae3dfd81b947f578d87 GIT binary patch literal 75747 zcmYg%WmH{Fuq+TfxVs$O-QC?GxCe*e?hxDw?rsT|;O-C{g1fuB^LD=6d)NB`3psnw zOixdBcXdsKvZ53sJRUq47#O0Aw74o57{nCtMFR^B{N*$3XJ;@lxO*>kEf+fvDJNqG zO9lJSX0~8p3Yvpe$1RDk8Hg^(edeh1vB->BBi|vD+pV@AD^Rei4$)ntSD?pG6*q&^erMgJLiW zu09M>0()b=A;x(|zUj;xi8jsjzY_mGF9k3AR?tT#{Y^mZU4(nm{`kC5XZX+g1^s4) z=K+`$`GMg9cE9Bnb|}&57rj2`*Y`e>fad*cRpi(8*XhoKUlU=u7Pq{k{)>wQ#J3lj zNY@Ye?w0~LdF!v)jRvM~?w?qZVYuIVB}0glMvj`YOqmfYes!{KME5yD1iyE&r@RDS zM!$%m@I1m$DSs8VN)jLPcb^?x?NqI78h!8b4@tD=mbrvNXFxcc7d#f^EL=$3y;YNh z-h^_gg;n-w)i++rL;`ph`{HFfH$K{=!g;iC+?C}HwpifzDXpTddA zatY0x_i5>dnxKdYTTx@2+GK~pXQtSh`C9aKTBeEbH8Q-MszE-N1y?x=~ z)8^OKja73iQmtk}9K!r&R%{d(1O>_0!IsPO1>4>`&*?XR6)|p(Oh({^l25r2=iamN zWyzXw7&gai_G%as!T11@w)$N97%Pc`->)*)TPPRObn3)smGf|h#SreB`N#lJ1_}O_ z*q*H{ZKz!ewVSCZ0Yzgf{6 zI<>}jbk?f~=?UkoW3kB#k$bcft=kk;@}AUoEH5P=!rG`9W;|9}{cOwf(%a@gP42tZ zF%Bzn^m?b*v%4P1lyZ}sstLX&c%s_ajOV9PtxgD$9m|n(zY6Vof~v{y&NljBByHq>flvNj_Y#k$5*5LB|#wl@`q zy@qG3e4>GcQF8mwxxpmXjm)#y(g?htUi^A&R==cm751KP^l7}-sb(cozC{!oSESfB z!`5fki(-6|>C%z%)IUh)wtjtLtWenL<;Mbm_2TpdUs>A@1xx}AzrarUUx^Gc1mJ~TLox_NNO^MCVwWz7~lpd9D+(nu+FZC zsU`JKGO4f5sw>;6KM~c{65KIE<63fXh;?ugt>lh1+QEHN7(p^=MA<>HL8v@SOrEKB z%{#awHMniAlxXv6MyA@7>wCSe43w|9GJd1Nt%>6`q6QbXrhxRQ^R(IH6BS`75k)W_`WyP~CJfIEw{|+j zraN%0-u=|9LNHuv$aw$Lvakq}+w+Dds2o-D*xC_g96Ts&w%#2QIuYjiICN&}hMbm0 zL#{9#jxmHMSR008r`iua@{MTVlUJlHF$Z*&^Nv^-o(!@&+58Zn)nSHOCQLbJKy~y3 zI4x3K<&%y1i|oMJ6L?>@YzqYe_q_MY65Gde0!rLGBiPAL9?>SLp%}&nF>59mAb)s! z@ z1ZMcShpwW{9INtYr`{$0Iqq{9gA}P3$bsCgN#6a)s!4B;Mxe&%=Wf=d+VLDcZ3-Q^ z@}LAAi_QH_>m=ee_R~5l5!qKKaQ)VBGGz11PZcV(vC4{63pwFby_Ms%?Iz+n=y8uq zREVh6)y3cpS>FU;5(-)(l&j=K)ua$?#m&O{aYDzw*eC68>NaxIu$}GT-yQAmUK!Zc z_-2(l#1bmIstY-gQ6IbtW1tU=L_mn;vih= zC&8K+gT`aGC~F@P+h6#{zvUn zFZ(kbJGs5nu%SfQQTB)(yfcN><0_QI$Udf~wqL43*EfX4u8{EgIBn?X4kX`Y11KhG zzdNJPc^EfpTt}k}F@-0!&Usd4V8d!&>1jW%er9`(R9^7-)0k`aViQW@-(1vOnTd>U zlf)-qLfLQ0maC&Lb6YeVM>C2j40dK>F5Muy7dK`Mz9WbFIkrEbI2!C!+bY!h#_uEe zK63)+0M6@?<@PMncsrFP})U3s@y5suAug~k>z2};n1n5Ax28MmttPY48 zSk&@Mwc3Sxr)&!kSV7o1i3?%nNd7-kLMOj8XM55lHpn+;*B=>~O26}w+kSQQmVzFk zA+9+eQTVC03mUd!OLLTI+jT0M8)d1zZm#%>C5FD}*vs{4v#;dW_{yKbuzkl88GMjO z{Ltqd_-`9bxhqX%G)q2MIHjCrFxolua$>7YR-Vi_zKUa?$q%juohSVLlonq*xq5|= zVTIqHYeYldA>3GmFSXn)HP2NM z9xT2YOhK6p7lt3pdyOzfium{H8$qBu!>JhX6XuId{Q$`T- z!o+ZszP9>2oR?0S@cS%lOSsyVHaDMTcxr2kfYhP?UL|5P&VQ63ipHtM!`Eu&}T) z&c8CS{D6D4DJ?L{L{YpF5g?|FHD`jR3w2J9$|>7)vO2ce0plQx?2LU*HOs-TL{T zW&g()>>+?@dcQ4rr=uLql%uG80-=dnr;57S zsIBlU!8HHqVc$W_Odtz1QMezPs)WqV$vvRAd0*hUg&XoktPm1i)$zF6fg6Y;M)vBh z*83P`**uQ$T#OCLX}b{66Y{Z8F`L(Gvs#dQ(fAd2!MsMa)`w>^OS3+!$^AUnc;wbS zZIPKOgU4bz%=lNFEQ*Jp8TbyPk+eAWcNT*P6-NzUP#&_4a;`_o-f@H7^2N)e^JqGo zR7$TgD#M7CacNqBBWj-hVy;-><&`eZn(s$Zb9}mbaF1u0&92)p98EqdJPh?^0{nPX za9XIrZ~~i18+MCJ&^if^YoqY4JqCg)%p|gWv#T)XG(k{L{4?V?^uB2$s7+&=QVC z_TUfBKtbQ9JOF7dSDI><8lo4w1mddG-1k^o=2Ikvsmza`XFpKbzN*mVKB;^$&0*t- z)+dHUh_dAQfpO?F8OA}qda&rk5A0?eR$4$J^Mk`Z% zmU?qCHbz*4?O*FFoqKrbq>AdH^@Cz>M7nCiQ;fFEKC1%jjCQcIwi)6Yy>@Ab@0=kH{xD;1eXhfRCMSiITEk>z~2Hn+1pD_cPuCHbV`YYgzhf_7NV7o;nk~R!iK*?x>jz zI2_?!6Pe>Z<-!I@^%Iq1B(-JV7C+!BkhvUuaId8Ow~-pz`mdIyfNKazA2p`_&pBd1 zYw~$yU0GR~Y_vCIxU<&MC-lDpA7K(2+!)Z9!CQDr|K{LweFTZ0GKX8UUt6lm>2BB& z5@W zKLk14jT4@nB{GeSFLy4zB3h zlh%aKJz~^+coN5QqjA}Gm zKHK(ibQhW~mMg7wj3))ozG{S}fwQ9=O(lo>`=;EC9Sh3Dms7Ddex8d{T`#ay1W&@@W@=gd29$lLBX1zKZ7b6gq}2A z$6tC19T(Z8XZH$L(_i^&d_=Qq*w`9{KZ`d#XltM<*x8uBg^!jP(?%TFwZ?Tn|Edme z>hQQl>YRA}Xu-51T8<`BukzGW;vs5tT#SrPLaAa?|OO@RC@e=Le8x!ob7BRuc+K2K^I>Q4!iy+ny@c z)bDu$0dPD{H}EwW(~Lp;j}g)rE>>MZn*1rt?4$9ljEqiDpJNsZhvOS(>`y z*tK_Jmk1qzUHT3Q$PH{hF@(8Q9+_-T+g&`pVEQv;N5lO|CFAFZxVCtSO#N~`)v(O{ zLz@+@Kl^mbw9CcictI%9N{c@al0RS9pFI4?p;E z`yV2eOlU{BE5(}Zw)l!RecK=sEQ>-pZ-;q}&F^&SQ^J&ekrFp-aU&*NW|zKtUS!0t z^*{EpWJNoD9wWYfUx`F7t=_tf5uly$v_`xY>5`@>@Ej|qFZfo?lgqTOTp^3S^E;c6 zaCt`Rl{fi9?Qu&wSFl}ju2ArYNDP8{iR3}~&hdQp=D|Uk8nU+dF@}))IAnBiS3b-c z_f^kFJ6Z}%x8Z2N+nK2c3kyB??iB&58u#LlXNJ7r8^Yh-RH zk#4TE>dL8CC__+ucL{A=mRVTr7l5PDC}zVNBMPCKSPxH%c-C|)ibw=ag~jTN??%e( zZ^R!<5UkZp+o3A(Ohw3z6KL03&9bxGsS7BqCspPlLrCI-GUiv}=Ce}oHEkCUBR@!u z2Tt?BV-1A}?Z--fH?L3DcX}_c22lD`7%AZGau{(jIg6Io$8lN|Pqolq?w0xoThtzF%+yqz+$ zbWgGtZ(HLmetxC%Ky{>7(|jx;FNejSu;GjsdfnZ^*vcyZYDHO0|3~+gnH(82HIAa9 z#HM;3HLt5}^&C!9?GvPy`1gr;1|06dD*aZI;UpSr713Mjia@fS;t@^e%SM`m$p#7n z0{EWV@b(9$4j=f4ela2RWX`k%2TE`S(F~_t&FqdC+vaO)dGS`y=dH8r!G%SdTf%26 zxD1Ubsvsib{o!=PvvdAh>sLR=rT*aWeBZ(kcBb~i!=-(Y5wP&l4}XETFBkY8H=zq} zNw63DvY&IK8Lm!{^GB9Q&2!@Zkl+o|6L;B)2~n+fM`I2-KH|h?tz_xo5z-LC=tAdw__55UT&y;^BD@7Kt&QJBRUh;jCXN(l~$S;QfkazbdrR)orT9 z?9K^PZ54A`H}#jV&-W}&JJNb>9x4`MKpnw$vr;RF0t*L+DzyX@ii*T5vk`G}DV1Ge z$mcA_ahJ>ry9c}z@h%=G)jEuzVh3efnB*!ls{D~^^uCFVNO6B;#KCgi#+rJuBPM@R zQ~@^+_d3NJoV4*Q{SLP{?yXqJ7_q}SZfB3=CZ0|gZ-mp?3a)z$Ytg1u z)f;_*W;J!}gW+&d!lD_V-{ldO!|sggKPl#_(;_(;j$oHHj_$jAzqi)BUo5_dA9TiL zp=ZK>v)}v1i#7)0J=I6NIz{)M3k_l3@Yh|RwT=Ak7x>!wmiGohd5)~ z7n)8);BXa$ExgQEJ#(*gJR{7_rBKH+VI$e*GJzHVi|`gc#veo75OC|y++W-btQ__- z@1(|RwV4e1i@UfzLvPU^q$t=>T&7CYvC=8Mwq&3HF-IMHYQ|}%uV1V65RBj>wy=XV z^$F{u$=wX8<%;m@P$hx5%L}c3trxny0t55Qyzvo}p1`lkHc#ivq9$vN+kN%q{9oap zLhu@mfdsV3fq>Ts_S(Gotsuceo`F+uu%?6~sieWSM>%VixY6p%%hg!f+7E>wM1{x$ zI^;7GkzRS(=hQZE!u;FC{Y-8OvP&AU{CwlBbu27LL-Muu_pdb7q{a^3 z*Wggs`zh?}TE<~6S}KYVlpF|0k(LsdR~gSNG(w%{9@}rIA*a`*&IP_ukyi?pIV*D; zO)|eG%T1-!t4r`%${Ce>?Iu7vh8D4}bMSwuklxWz`7G2i3YtJ`j^m9{p=VWvO=-Q> z%M3c4wKnq}{0j`@$FqL)Xj>Jvw%76U6{QE?KY`>tv(7N?gS|G6%??R)?YjeVm%q%Q z@r#|Rd&vr!jh`Lc2q)|d)IS^SC`)~TproK&LYs0*LpHq;`C`M&4}uued5s>y-cqFB zDj)>v(E8qV?;~?JqaxO?-*Q2ihY1H%kw~W2dTxcQC zWfD15m6-Y=BM{PZ9VZ=zZyN@U|dwg7~!KV^_BMpZ$pI-r;8oWR(L*- zq$vD1-m3RqchO~UB7y0Bp&yxPfb-fRYLp9n>;1!%89go+_w3Vpr>}&#$I5ZbVf~`E z^Dd?k(}F*|wsW!Hp0iW%j>h(nGiEvB!Ww%$l}5-NY9nA}ZVHyI?mSi9nqTZ$*3B>* z>>|8rl36gAn3xdo*kQwv2eVbGPkTT*%YDs4lty5X(1^I9W>FT@{AlYN4tnndAJs+> z;2UMW7nE>fnR9%UaOIn*YuTPK6Bmw!2$iUd#tO&MOE|_OVDZBHRIQT_1#xu%qNbK6 z5PRP2g~{gb1L;sLG^TxhvPD;26g7Pw)CtIxLF*Vq%xvD$kc4=d;Ud~DQGlpPIIA^5Qo=Ao4 z20))>A!kGIn@O;z<22nfMlLS*^4Pm+l#5W0!N{d-Sxnz%qU?L3ENG)O1)-U?us z-oi%D^Y87#p9)_`I{*FF8(qAfB|r2VqG{Ab-Zmeb|WAi{h*b#Jh+QP0ve_27SPjc zqtVOV1l>)Un#%F9#nT$w!dfMWzpz! zJR7a61bYkvEhVE6FSV@q<5YLIh-LgbMmqi2PIRg-Q27JniUZ@a=Z@!3t8Pll3wr^m zQXC;Zs2dXte#d_=W!_4kSmGu=*hiA8!J9OO_5uCW%Iy%F`u;y+RQm73b&ThK2qN}` zgeWgQK=|;6)qyg8zQu1mrAj;X`$FT5vp5w|F^lnbK)D77FBn9XQgv_o8i`<&aIqxQyAF-sewel=;L z;J{P76q9Dl44+5i!TYcGL!H-7Xdkx@uQ89u*L%+uA`4||S7;ZN>l0WaEj6^Q3J9eN zI7AZcaOlAWv&nYLlV!yR@39DoLJauq$*5VOp?+G3v<_3CgM?UEYMHs%P*w6C!Y2pq z*Bx)hojo3&3JsHcaCBDJjONLaqXDlNLko|I=}(14Z$koGdk!Q06_dO~_>W_g!qK0= zbvDnR&vR7EC0t$>XjpwGdXX_toJsj935mR)x_3uS z`vyvaeL3;v?R2n8C=W0CuIV6x#Z=~5_*iu^MsNwA%>y7oAdu0Q@nc2e(z}FGAw9-+ ziN+-%nJqtMEpAyeHnA_)u%BlDqG*7+;L!z1CWR5-4B`kK$QLuE>z>#KvHZk0?uGV@ z&e|kAZZ>$cvLY*>Yz}{FcwBB_0#FIDEZ@9&cLnaWJ6v9;5Eqxzt-2+&t<=z z3f{SO*^4i`EK@GBcs0vxH!NOfGcQYamx%A^#2B_c_%3N2R-_~xiCG=MWZ2m=I*Ndb znou*6gzEcz*SE7i@H!dyd{4Z!PxN|u^4m`4#jMZ~lE@3%=q-fnKwA?JJUi_gd%c=E z1+Gj>c$G^Ai|$Jb(-Z$Fk-M2$x`0*Wv4(w(nfB9}5EFr~YYSzk1ogolhK{;(Z2;x-` z$E)lD=@fD=;-E7lK`hDcGb3dz5$?{~a9tc<)TTWSV#uel6Dkp{Vjw}nz!d5~=T24X zQqk+QAsqfG9R#H|ml;-bmW{2$#C4Ik!yyrHe+5avo1QM2QLER0p+y~p#^@MNoG}a~ zQm`pzafe)@my(im<5cQ!4Q6ToF*Y*`@mI|0E|3`6ID13luvQNq=~)bqjg@SNX1F-~ zhON_R9qVW+W%L##RO>oo*wfhW&p242ag0KQ8h9q;-W@GO8FlbwY$=A>@x@a9-4sbw zRFuW+ireLQ=}<`6pS(aRmnZHLy<}rsN@?c1CjLkYz4&;Rqg3+LLWAup&5O<254gS2 z97ezQr!idwVnHlo0ik@G)YyeOD|}$OX(r^nwc$vx53wK#x$T?ZWTN7oey`BqO2@m# zGToI+O^tN-_9deA2(={sPT&+~#=ycYaaWp7HX@7Ey7}>oa zXi@zu7L_%zLSK2IAFua&hfu}hs{_y#U!8Gwhm*VS&jW`NMu;kPxdz*s*&Ns+2D|lp+s6!_wl?nL#&{(FX90XbnAGj?qU@@rU4Hp($@9mBER~AiW z#BbtWr0rg2C@J1P_#H->P|zB^G$mNBwm@OgKcEX5c9^`c*_jYojAt-STZJOw1|(8M z9a~4pE-?v2EM9GVblROcE60t1(O@@4Ah0!|z%2#vS4NoDGKp*oK4{B&Kqf$GU)pmG z;C%MiKiCD(SsD_|SLKBG<_8_jdXqTqkB4|VzoUS7y~jmCtfvQB;s`a8m7!YgPH=0T z?*WEV(f!NwN`09WG}fo;KllaPykmFi=3c0%yslFSo1E`EP%PBX*4pFl&jlunWIn94 zzN2tdXhJ=TPVMP7o^2c?_)2GuCva1>ct+iUMCA+8;Ulb5B}N>spFBwms`Yp&3Yu70 zSZYQRk(qKpj53BERS*vPRKLLecn!jAwnWINA}%=2Jg?;Roa?9ODK^&(*69$MoUWzcIs5CPQC(^(NUxPIkRAq$*?&>J@v!0dw5;yM{K4-o!Mb# z4vzlEkEv4)`kFrX?@8j~{x1(S5<&wpgy}~QjbE0NLH_RnV74oDn3{~)Slh2pv)Ca7 zvKznV@qet>K=HYq^;hC!-#9zc9k^B#HY)#67D=ktWYC~y=Z5WA%Z+C<6iL(8qF%7M zvaT)55rA$mrv)^KY*HUWdqGhFq#6q3EV3(h-{Ml`1h{fe_4yIUc zkP!D^dpr2%aJu(&Rtypvnp88VN3<`YtZ=$r%73Oz1@rN0uRF2$yTjhi6y!EJr&130 zSGCfKH!1OV7E{Kb=3|lCY^9Wrp#=dWsny*rh`L{y$-#34bmxd854I@$dyX{x3*0L4 z;DXxJ_H#V0pK4JO>146bV&{F9&f*OnRZ&44nTS;t_Df{VU@HA0{Kj2n)R3(O z6{lgMWn*29uopV|&EYE>!O3Z@)2t!LguqZbJV#(V!<-jp_I%X>B@)9CWy)Q)S*ykY z&Y;Z)%A&NO$@{$9U;L)g-jC)9m8n1tuQO_78skxIoagb2>9xHg~mH# zW0T)2Wy2S3DyKFWBs?Uk!5&a{q1^nM$L&?1rI?B}+IbxDs=Bne+RgJ>`}0DZV@$Z0 z{qj#Fg$#Dc;*=y>eOz$A92wBmuYG#?skmBG$s%4q*-n{=_j(&HhvU2UuT+pbLc95Y zQq#>wH1XTQ1rP5KQB$;yO8N#gJDGAXb?5gUcHVerh5A>Z2$@}9iFRBa)E_2porO`x zSGUih%{L@vCVo?v&^!54;?Gyd%*;$U64 z0dGX%a@BqjR72V8GJ`^JXrz;mXw^s(vL>e)yOuLGM01tv2*Yej3{)AM2ML`?b@_Bt7hpWx_D%xOT1b zX)2TW3!bd~B4)E-==w9*m^fOP|KqW5J8$f(W=D~fL(*0zT(4*lOO^fyR9{6sRW!TU z;t|ug4mIY-cQpbDoaqrQuhfx9)@g!vXwb+D;z=t3+)R-Cfa&Al*eT=dG9zK%34&UL4AFB93kKSviLJS zd`R`H=YEwhwPr&d%E5^ZwnImdJ3-*^@Idzt06u%BK{|sW!N~bD^)Xgv$jA z$5?Rt;_pMqk$R+=+i-5X0Sd8>5WSG&P5)P1*z$O3D`jO(Y>3g_K(iGD-?r8ZDpbA?#y@>v^?0vBuB-u5mr* zOoW*K3M^R$o~ltGA*urU40E>#mL2a8e|UOCJ0i!Nc$`0DqpH%97o=8eMWGMALuW%N zWTMGnlxRqUeRGIXLXN0@->Ym5e^EW-xRp~e2IL>8m56X~ft8hZXn&HRulB}t({#09 zRlXl??d~G-`o&IjpyfI$WD?7e{P8HCl;oE^&GXSRT(`ftzL!eqL9%WZ!-rwB82^fZ z%NjnG;-a3Ltv@{vSR;DrWR!ZlPO#?;<7RUBKnhoKRCgGy5;aF_!kZu4u0Wr~IzTqcR-)-?Y@3cJ$EX;`C*v*$=$IywqJ#Xk^M~WxiJjbe)%_&O^6{VVd6u%?`H2xol?8zC88v}qM%qzw$(oqES~-KPq@v1g;5=_vEW zAPSKMzDCp&9;K?Em3QxX{y{;*pyr=2ETY!ABg*=W@z!BD`F*-G6YgUweQYs$H2)=3qZ$bVz`OG%x?1<`*?%9oscQ?`WCq%mBrUa3+6Sp75U>M7|KgW=Z$7T8!L4#t2=2z1uFj*5b#pXon}LT ziAbWDH0gCku)(_@kaLxFQO9Ut$_WYfXTW4aiew6rOX(jy4NK_eJS?Y;ymNh=VjKOk zRb+WfJjW)9T8ZjFi?`{5gxT%LwoTGi>RiM>L0=GK`g%>B9zcp>*|rBC%2f@Ajy|i# z+wtt%+eRvIaWgkdE^W>AR6wCC%0e@@MGgf67f9UsW%aURYpDQuy zJ|_bVhUg8_b8k_^tb&_4>mS4%HXoI%R2Som>LUI84-r&=|3M;r6 zDYL`5KE|)cFn~vbN45g$VUO#b{GQun%qb-SpNp+kz8}YWBAbHK6+<9i2GNYyEQvaE z&z~G0$nr)IKRQYN2I-9d>g`|wr;N|)`ahDE&W(tzUAkEJQ8YXv_7hIYPmtH)r45dD zI|&~4pV1Ogr z9xPAlIDWCq_RnQXTpmd6u9h?O{rG40}){mTr73Kw!{ zGFO-}DB}e*$cd}7hkoIQk6TaXqY+0HGHh<|_es?NG&qHz+2&YiSO;>Q4=9UYH_%pv&J}fRDhkH^W!i$tFWz*S{hs$Ry=KbGZZ8$qy`h&|HNKi6>Biij zdcCmcv^xwYty5aB0K8c`Sd^s!?q9aZrP)|y9Q~L3JGjq{N0@Q&^U$KgT@3I(%6L#< z8BV}eVQ@hmb_@~{l4$Tt$k*BUvmb5OqEHz zvFg6-sd`{z5(cNGX{BYRhvzCNOh>KzzuXZ@o%4r>wEy@R%2 z^Xr;2Ev+$HvsEwGlaaiM9>K(#8sJ#x*P(zrV4ath(KJ)>eGlxs+}fpU^Lc~^`uL9L z-DKJi{fhtgf&#_PB$RoXz+uz`F>_QK)!Z&jYA6(Fn{{I)P~$&C<#%^qz#@djRTKYs z73?9WlwJISQDxYnhYJY>)%&}gI+BMk-RKh=_N0w^c0sTVF3niBT5VKL!bQ5yPw+K7Q7?=wpY+Tm|x2a4+4)Ldq6aK zQ|3_uAGLE`wJ}WpP`i2V< z;s-P5Pzhl}rF{oyXR!{SMKUK|s zg+s3~>W1Lv;n@Ua@I6x$aw$dtbD`DbKspdh7{z73mM5J60tDJ3fcSj6R4LAJd!W0& z9}4J~iLAD`vRF-%pDZ^bpPil6G&D#CLnGFBT$*4o>S;Z8JAb4!g8XZkZt`ms#Eid& znfx;n{Ko-!*SN@fO@ENpJxh0%x{Y zUYHKD&NWxjiWx|$hB2I}o@9mbOP%8vDs}2FxRcfTwquplxE zW?k|(0mZ$rDqver31;xuzvk}Tk88Jputv>GLX=%4ar`U5064Gk8AMv&rx|HVZfD!kGf--T-fh>e+L)_%y~Tw zc%cFi%_h$uP0!NA;hk?!9|2QI0>a-~n|Vf;<2gh=_cIL7 zDRe4D4A9f*a--#XNBdBEtkOFP6{S*6G+?>ji3z0#aW@(~0iOqlWZ#`o`L1}N9^%|t z+^uB+w}Nv3x@ta)Ejj4%PcE@hKwSXnv&;0FSzBBVL4D3`MkTPdCxOD}%4 zh9Mw-27;4mx)o8WEM(DmJs#`laFmwca)A&~eUf5Foj#9Opms8#OPw|B`2Oab0Hg3Y zNnT_nMw)!NJ-7{+k=yTu+i7Qr)DJtCN}<$!rrOYu0(vDJ4u=)+iBSGleooWBNi0q; z{WZ>QVn7mzmzNhWX+&c8YIg+AXCNAvj1$G6)lI>cy9gupFDnk{yn*(xl#x*$%4BVA zEy%D%v)Z8G6p*t1RiUYuDT`!Hi%4xGgqOUlJxR6I%#B1Cm8J)X0~;j=nKH%-&VU+! zC73;j!i|=VMf$c<1}E*wJ6Nt(I@#oC`f@eG1VZNRuwDEK1;~@Ig3>q%as<3TW!=j+ zPhG0)7f3_}8I)aJZcFWqWooh)*Tt;+zZ1eB6ZHYkX!PX^qpF0oG?(4dOxb<{%mkz= zK$m6AL!(dr-wgpu5DjFR-8yh;l^#xK&5-Pw&ci90=EV^=RRN7b0CDjG)asc4V05?Z2`A7*8Fg+u6{d#2YW{Zbx0JQO&Z`Ve^E~sb>lc!wMq5IC`iXQ)HV=+P63K8E>wYR?hlTc5_N&{ zML9^p)&56H1i+F7#TvRGT_p3oZjZLc0&gO}7#bR0dYu(Y#YMiz+S}Vt?%#as0k$O2 zpynq4W+zMaAB~NTw_Yr;v9TRXuIH-_Sv)R`{$3yY^yw3DlmxKowMYbYTiq%>YT>g< z6)eQh*V^#`9e;m?#`nGvb!bGqulZtOTU~)4%5)nULy?IYkEVJ4%phl@3jjBlc1BW> znGD)ca)o>zP%x}Y-{?O5pniCLy@Bqw(nS}+_?ojVwW5bBFija_Ss!WB9w26>_z~O2~hTV1nB@CGu ztFy3?D3O>-F$=|SlKU_Lr~ONt%s0v&f3FXqh;!ifi!5)i4|)Oy6TSryu!RSJ3SPY(#Z98Zz^#Q6I2BnQj9T0f`}Xz(@>Os zbz04;Xp4y)IPjdN_<*>^+=qMen{waRr(21>EckXspYbdn(a&<)50oGZ{f2BT0O71q zw{UKj~m8mbIcin6~U6rar*C#1N;%w`%>? zP{6$-lM(=wq(Yq{|3L$2F%3>qIF-|xL|fMWv@8~$$|21Z^5!u<;oaVZjY|JijCH*g2! z1>^$xJtsRm;R}%5Hgog| zdm;%IOCHjXqe&Se1*uobG)D@q(i@bq;#62um$x*fEwah954)*`;(Wu-B}~xc+W>AL@DgDc<0hf(nf&f~uUn?ssKl=bEg{#B)0}L?tUoTDki#<=4Kox$A z`xCfM#|H6Rf}KZ{%Gq|MNd;DU$wfL7MkX&Yo>D~aaoR-{W>;QKkabtpu+0Nizr_XB zBn941vWVXXZ80fR9v{knwS}Uf=Y|b#cLoTbj&)yFb+T?mLO8KiUD6@hclFdTGC3Ki zxjfL8$jbngXNZTO>roQQLDD#j--|~AF@xD=W_XgzqMHs7e@Z37g;M{bXi*VeyPe{G zd=AV1W9u!$;)(< zIe+_U*?aA^s_K=hzRduwV1LE#z-ilHTy^^N9jCPN|RDcXmD`ww$xJp?H~|r zU!Yju%>isd7v@`l}&dmD8@5u18FC_1!g;*8#&=47*TPI90rHNc# zD?XP1IA{9%AE0ZA@-1!pafB*&05c$x-K8_$pej+zf9>d_3&GJ?v+KR+H@-;X^B&9k zhNX#_2PPQ7^n?=oEoqqlchUfClK(pm98fXw(-APLy+Tzl`+*knDk zoc0lYarhIu7}c!YXr_CR9@A`s1OAjn3gsOAmM>WTlP{8eGBMWELUyT6=HqYGov+{H zIG2Po=fs}DM|H{B3T@Za`qnq&%L7nr?0>m>(9uK5>gC8<>uI0-MPr0&BXPBL}$E&|6~XF42#w6Ep=O5M znYY~mbfW^cWK3n7O;K_qmXm!VcBZ3zZ7~iD<{#~T^%<63Jm0A}%Kp^ShMT#Lg;%@u z13&*Ausr-%l_4*z2!Ey^ejb|lpMEu!w%8yG;`V1O)eniHz6=cnH8iMfKy}25I&k=2 z@Ab-k7w|Ct*MhzwFIN3A_%C=Y@cWUCE3pDv-vXD+S`4ch67A}0C+ajZ7LCx$Ri7l+ zc*4z|b%D+JuR}BRAAa7<864nW6URym%i_uiRP}A6vCPt{hQXNm9X}3(KdL}kQ{h<) zh@9i;?oUZ?RgWI>|6~;41jtlTu?}&?*5Q-4w> ze#o{_6PTMy-Sh_gcXHayy&dYbfrnlwa6JpK%vG(5o`HwM?HE9>=6H<3BM4aDJ;0Ft zFG2$VyNeWFiRtP-S_CdELfOJ2T=E81A`hE(D8#G=a0uNO#6ekLfvqh<$&I#n<%P$9 zlU^#s_n-UJhm@2jB`1gEvRMWMy#jqBBPfi_-QA#bKeWy>GwmBB6*ni4vsp;et!=o| zF-%l|(ZTe10+VVx=cjo(XAhmxHqJj*IWET92M}geBAeH-JPxMFnx?7%jK*Vw0Aj`N z0?@ek&sRaDY-d-6Ru&pwUd~AOtt_P8a;^sqJ`eUF0s4}Fy54ZMOe2}!^+&41c^<+W z4sEnqIXjr5F4Jm6d3kwB7V_@UCrF1jYbKnh7CQ6PzDn zv(i$(AJlgVG-IO^5k)d+)T{&V_yM{Tdqokj1I6O%nyHoqsBFQZB1#lt*q7i?6&B84 z-eHcg6Q;ZpV+BawXvFl+(n+jsHwmJU2$o?K8 z4+MB5>QM1cmvd3^HEHdspwB=ZPBu^i&;-IyUI14i{ldLEH;0>m+32wM89;m_5@A^A zUi{uK+93pGWSz01m1evxubK*VU05r@rz*44tv)TEsGNmZCfla4c^D8)B1I8mKn=9>^j19ru;0 zR}W{)>1Vg1i1=8XPqf>-Ux`1;CUj+azl8q&x;5Ydl*3OqOSW%4DArO@gtRZ6K>I#$ z)lhHcw%>b1aUBfM=g*(vl`S69)N734dwO~%>daLmhy@7TZ~mftzK4Oy)u=V)b~($w zBbUAgYCeCU7&GV#K{o^J_9{o+6Z9XJa5)vm_JG>GkGG(R8WZ+t}%mw1{ioEti#{dpYoEJ9K1Y>%eT0rCeelM#Z_Z`NHjg3u@U=lav zk0;T!8WTDBRCaivHa4sP$e@oZb7sfN+X)@nI=~)E?Ph!&P`&kQ=$@^=aLI9GX?&yj|ewcK5y0fnyJ2>s? z>w~_+ik`JO-|S~K8bGQupMn9{7MKETux4HZ)c#0t1O z@q0dedD2rx*Qqg{QWBw z3=$gpcZ{yE5VOOy$xJf^T)HpPPZ<;AR}!&(jvl-qfU6SbS+46ipb`8n7rjP1q@ah@ zOob{5F;VuuBU6h6eiCLJ`9fCxTJ|s2D2! zK_|ONA?=0)T>;m%g_}BBJf5XcYGV*lq8yh|GvPNX7J7cjC9pFB-hHaOn4rcx_0LTp zo(0rvJ3xmEaGK@BS8jLx0JsA-!S&(Uj?s697B*25!DHcAs3vj;R^Mn6Sa(#FfPlOy z;n?N^n1jpFhAAT+Z;t6_(ImE{<&|=1$l&pWgoMs*!_Ij4_`+#OB#LCXRTt5onO0~GESN|JWCH5HN z@%RubU-7i&{oAYLC*Y2AqkW-Z!$5oIv1W$SACPEg0v;AxewLygC!C1KIxxvd)TMV! zOcA3#^f=sKn6Tbn1%~b>sxZ;4WvEcnWXCj3#3MZzIss;?^FVt0doV7qEUXMeF0E(O zB6XDb)MDNj6uLUwz>3m3R8nA}XgCG1pUyV?i{%teY23!hd3QQFflz^M2q{FGJ*-XN ztSE2c8gfPR>BSMn%~&Bf+2+m>y$G~E%>;bdL%0P(MLhbVkQS6mTtXt?_GLS5a?2^~ zM|?=m2VsvKg@6PoX(#0BX|2OBy|k~vp`oUEQAIaa{X=Un0;1)PGn&cG&mk&s|9Z$k zGHn^LKR(wJ&Pla}6n=@&^M3vchmV0lsU)*ci3_GAE+!U;E0QMjgrM{ljqL{la-Og+ z?r;G5r$LwnbT5`%ZGYYbW zBGBWskU(NlCoBQfLN1{eu%wQg3S})XqKXITSp3<{{B@Evk)d9VrlSO`MUD!2M>rC0 zw2Rv1njGglq2zN|{Z!ow&0`6b@*ngL2vQb-eN2+D3D|E4V}lirQaDSgaKMg41=qh4 zLvF6FuoSV)GgLig#mGcHD_b_>08D5FTdxR`vrTtyGK+Kh}AUwx}3Gq#B{rcnh|HrAZEW z!}EUI_l4utbCkWELxhdS59BsoGovDF*Xz|6bqZfLNHWDlwfkB_+CovJ8gc z6&v=VwzOYhhxFUPAlV|1FN?*}n<*F12g<-iE+DoDcy3%UL-2SRUvj!Rf6WQ62 z9T(qOn<*OybA{SsY*OMyv=?7A^n{$TK;L;O2q$%OQj}T8*F60_Cx$vqkSSJeGS;w1 z%KY>ZaB$!o_DobbikPGpsHw|z11YzgDL;~en60kZBRSLKY$?TQ zVKaB5Chg5?=_Jw*!ZAkq3NV#3`F>R!fvEmMQOAl5up*PW&kzpbe*KK#>ko*B?JlYLO&#U(+T+mELq z$~~~BsHZGdHVXkbCckF}BCKWfK5e#`FwTx9$0!x)w%XuT+x^05f0v*?*`y?yT%dMx zCs4o(w%h3==e<`BB{&Hi9Zc|P0P^6O45eyc3g`7l=Bu614m{MZ2Q4IT{}fpQWhYj6IWDr(zMH!Kk1l zpg1|#L2n`q`|E(vUiM?Is$N`YofPbeUDBII%L9P5iA#9n+k%gPP9r^>R5nE+HH4e5 z&Hs=x+zI_8+N10==EZQjBudNBnmE>bVqza1yd@W_vJ%t#pwH|u(x~B=Lahv#Dju!gu$CM`(Fs1G_a$s zs5w92132-3T)FX&w_={spa>B_C6#Z%vs|3q1K$n_(6IkxlK-Z?3^ASi+2GcC@~}%8 z49Z7vsESk6Iytdk;9$ee;BgVtKF0&J#iV$G>3g7YOhH`xO@R@6Q(*c{olXvds~Se3 z9|?zw^k`&YLTt70A9b4h~V_m8W!^D9M6VY}?Ww`MtqJ+|Pb2$p_NqP<5e``@g$H(`)QRWK_L3S) zQs;KH`T=y>-c`?9&S9hV8EA|hHs_2O$9KY~A zX_SxRZ}qwuI0@u+VO6MD)csX)F_~xHz?|XX^p%7320s0W}EY^dL zf~kFZ)~i}+OQS=YG%4Bs1i6vGhAC@W-@^x(S{RBKht(5K)IrGqYz+}@?r%)z+n!px z1g*-+zv+V*s0y6B_f)yfC2$DQedB54WHkH)_q9toIy)FWE?*px3=ItpY)r|$I5}jP zyR3k`o(6{Ah^T=7@O=MEP0V#2z)I=3+(4vT z+>=yyWFYo>3Jat@CFjJc8c#%@()t#ZBICw?zwh4_V>eBoI!CIwsuTeDza(hviAvzk zt`$9N{`J;rKHnPw;@X?!{&)Liz8b2#yL*4C2z6v+B;Y*3h8!IoeIA%c#lXl2&XYnN zp)3*PJB~VWZ1}n zeZj81KnLizpD0-Xq)7(Y)c|l`Ap5HaxJ)o$R^WFzdk0We=vkwH!9ulAK6V3c{-YrHgN=P5KplE|H+^Y!&54E&6U;a$NF5hkey6lOU(08SGRi~aQrdw(?I zdU1EYk=H{goTU#Qu?NsYAge{{^m-g%4P)!DUP5|p=5yku|1weg7r&A z7a$kz7i7#?iP@L1n$K=vEm<}J^NSt&DZ#rqPTJra23$^ zwgWlc0Boet61DIN^PRXXY=IL{S5%B=@PQ(dee&Oanx_r;Jy0AYV1Ue~hE@q1u*1?+ zq#A#>OqnB}1{;qXCHkRj`>^{>J872L1ZtrFeyBeM1g-lMIlc4N`lvYqJ5(k#SWU&)dr}HL?j3a{|qm z-}Rzvco-2d0=iu8Mh2DD;8SJe0n0%0ZJO+LfUf3DFBTM zP*Mmpf62jpw!=zI3S#?!jwyEtW@3 z(jQNbn9p5YGMK`-(C<%1$ve7*IkpgcFe$N)YiK30*WKnlvgvN&-Bb4*>44MOBvW1a z%na#3T&?goaY=D9_YQ_XnapgmGj^ZeK6C>N4ccSY-RuWkg=6~u)X~Ivee*rNJ^H|W z9W*0ajTQz`KYyi>LG-cD65tXe_d!rUx#o|)Wr#Ol1#>%z;o1rZO=>B>6~nRq_Y9pU zkVGc*lUPTW&>f;*@ALW4qag2BLL^Xn!S+EJq;9+W1Ny5~2V}6yeJoi#$0yTjk-{?b z&Yvm}Q`!=ckPscdcPAeL)=$aoyf=NR+AVYS&)YDr@`>V;nDn{>WK_Y~67Jh0dU*E; z*dku;Qpb*C?KBEqy(`EhD=TOBTUzOSFI+ey8IgxGuby(nlQ2_ez@9WqrCBn9gb`og zo)Wm*KK0E);F5fBJU})x9$-yKPBvS1dqlnX?j+p1Npxj1p@y>7I~TpC)Zk>FuQ-0B zxJJc7#S3%GEGRbSr=eVK!sF>c;?1NJnsh<}b{>%j*n`82*MSqeFUFLdOsNqVpHc7x z9b>vT0GEh=nhJ3Y75x5#Bg&lA5;_LDU)+7ExoJ{bmp2D6ulPWw1t{-yy?e!4)1eWXo&);v=jf2$H9?uitFpMzp83w zqpK;9ESWUKM;EJQB5G4HyL=Y=n%cGFSgABL{Z=gjZ+(>nZchCOYu zyU2lNAj^^!q8xLgASCmr70comydGLY&8(jXyb)2MJ>W<0jYd=Yf+KOU#JPy2NUC-V zdxYR1m!WQX$1m)kkDL5_FZqVMGe{nk>Lqm;R(__cavKY&hVkLyqeoS@r)~}PvxRY~ zWEcLIKBn*26n2g=F#}L02*ItVmI<5eDE?X=39}n9qwqr5zbTfg!L)?BwjJ5?is=Jn zOEN0p>b*ui3dLALny>A}VL17=4d2(i_`S9w8w7%7*6?ouz8#j6SCLM<@BpZC ztO-_t6$-{z?3Sx%c^N0L2AeAa;+zHpuF2aqthgAhj%i7&;mg=b3yPej+_v)wqZY{m z>kOQS%QZZ@0ebOVL6`+h-NfN-ibKq34&m=v>)(N^O^DVQO>VQ;FC>|Ui`(!7z_hEq z2|QWOK4>KWuGDbvY)9WkkBAHd`R{Sccd(D^v7nDgzXfy}@|L!K5cbpaU9dXUWRT4e zcZ+o2 zUECvH;0~bzgMk%N6En)88j}nx!s}};=~r`RjGS{^*IH_>6%jywe*Wv1J8THM%*JO& zr}G1scz?;)@^I*Z@hM*)nPpf~f5bG6VABlF4Wk zJ|Bb_HW>G_USCKDMc>uHz`ucvRE73E^&(R+>Q_nO#;UJpCt?${5IgiqxSk$24-p4O z-k?19=om(K&O4XKY|Uef_{&_qU7xO}SCsWf>hSA4A8J$T z5@*yaaX^_YrTb~S+P8cfaZU+NfrJsNf;e>1gc*PG1ckv>_fvc_nf!dB)4dLNKDwiH z-VE23tno)zfxYER=aq~OoxKM=+)nR87)Ee~oT7Zn(ar04C-(@;DWXF8g`HNd4!L{W z6*)9G?pyjS#rp(#2y;ds_HdNgswIBMN2Yhg^pX>StYpGe5x(NVRQSWxOYR=bh zh{UBhTYcTN3nzMaX?BEgtBB#}_+(#s=1d&M?9+YuZf*0vMJ}rAccLi}aP&9mXrbfc z2Fn;R-f=r|Hh}E&sPqdnur(X4!gbu8)~)+KB&S9727vKRVp6`pj08^E)%=Y8^ZcKC zQIP4z2rg-|`veUPJ?Qa?#Wdjl6M>2+l+7kjJ>HWl;iP`-4J{K2Z7bU7wH`41>M#WWa^+HZs3fuY0uF-RH5LAg-d)rHw!c>O?X z;bd*;j3wX%(dT|TVmvQvRzWskxXj+g<&og`Ohq(Lg|68|9k$bBd2dqFI39-yCkbe5 z;D+0<$B|osORBaZ!%jb#d9~d&&|r&!^~WaCYP9Pva|TL(+55OqRU9sHRVS2C5333C ze4i&8QiTvfG?#ZE|7fGADMIm%@PNRDPPh&iJc~mMGu2YY-(M>Ia`J+6PrC$@S**x4 z8>}I8pmbcAZ@UL6sO_HySW!w6cfZ+b|Mf}zX<>NM$;m>fAL2_PUuD((DL+5IYjKsJ z!}4`&gYcyERr?piQHvxL605p5+yg2{&>$Qpp@3tA|6R@{Z1sXWo1vg*P(~UfSHs*S zhxA=)SNkf|H4GUm8T#<7`?{qEB*O?p6$Q6XR&e)ofkTq3kPN%u{+ifTCX_E65Alcr z_ooY@0riNUlyyWURaL28&U)o~*`LYCM1e1!usv2iEGUH!Eimc_?T}K6#N7p3b3FN< zs|cagKoZ3|wZQPtj4-dDXI95`xF%)?ksq=MR%ORkV{;!)SEcj=9}k661&&&tBVe+} z^`VeXgs{ZqgDCFy$xt?_Q8RjjMg{M%F5$_>)wLV~e;y%x04X+enFEzB5w;|ut&#vI4K5Tt3lR?aw@10L#!V9a3u zDyL8=zcK!x*A|nzCt8A9op0y&v#ujjJ##K6*Tgw%kTURk8z;4hzz}=i>wUp_k23^1 zwaUOtYCrqyW&2e{425Mh#!!J*8)SsNn8Js;h7o$wa{YC$`u}(V{t`|G?1NB=#cCs{ zhRlA6^c}$=u@Of7>c})(tf37ygK0xb?d7c%DX&a7Y)CbygcWJa|_YkkUI|z1;Vd2sU zoK^8Q-*XnRGOcEK#?*#wwDx6BY_~%K(i1sCB-rb|g%~-HnxqYb{mD|OV6)pDn+c{O zU7WMxZ#N5v#-f*j-2(LLFIG&R)gy*B%X{M!u9>BIug5lb=$g>K?L7tSoUJU0 zXi`_#403YJa#C+GKqY9j0+FRc*y28Wg+zzj-cMjpThB8rwKP`hbWLwO zaNnQRuD>AvRml>&-*V@Ag#%L+#eLkqsj&hbo4R)pjjeSCe#CsNnvy=^X{BFu{* zedPPzT=c3IG~NVzd(k{xtW*NI8q^th+fWY~B53C%H1vx(7?X^8y|J4l4bpr2@$bAa ztOy8_)ia$#m*3MDa2PxE7I@1^(blWLHDjeC=c+ZiZf>T8&!b~>J$|I5JQGDLyEZEc zE`Myy_S$+N%w?Msz;i_NeG$2{ZLC~Zk;mtGzv6z|^%(NU3ax$8^J84RDs<+)#^v`M zYY?Z$a?~iF-TgB5NlKz45X%L`gucoa(Zgis;aohQr&kx?I%$gISe&5pdK6? zgj8g|WOp`OijBTps(z2ll(m&Ld7tKS+z=h8P{ik_f@!py;Ji<@+<0YwTk4>%gi*?PgRukb^5AJ5Uv+kIP5azrW9eOqj z$D^4n_pw^H+&P9CDcK)!U6=wZV5o9lQ{xr*#m&glJ;kn-??w5QBz?%>gbcAws{Hpd z5F1!Zk|CU2`2M@)X$F&5GBn!xELTf-`k}Xm?B-y~4PZa&usiB;Q2i+Ta`PSB z$FSEw(3kvw@f{<1H>DmGQl~jV% zsw{!5U?6%VL$upGJPE+!e!!wpQZlrk&^RR#xkBamA$pbH-C{Ob12v$*lWiAEzCYIi zqut(+rySm}pr6=}&YUJh06JGc zD9hZB5m;gwpG2Z2?#p&blxJbi5*p|lyIyzR9#BMkzI$ODNnweBay2y~wu@GHwEMfx z)F&=w5S51O9q!t~A)C~HzsPcBLSxsb`nw>=pDKzO6 zr6vb!`NAmg6Il7A8ckc&tL=Gi`PZ6$U>15RR3FE@DrTA`PHA+OLwGc}=KTzwJ=56= zFBk*9+21u>k%X^z&4~2G<}?bJbj$6^ZO?pLv>$C}=e%Bt?|dBHz-z64WHFre`8(~| zJil|rnuze(O%`ctO0j!5v3ipm*`lLaO zTx5B01%kGuM18w1!Mz!OzlGa)c`$QerOA1IaQ4@lP$J~G^#SB^n*-4!B+4r^*lO>% zrLpfKuymqB0hZtM1)2hc+P{OzRb_dKLX5K6X-|DibHhFxSZ&}9AzmAdrp9#B6TFYg zg1>-UTW+OqJb`OasZ08FP45VfmAA2Z%OH-GiP+UHI%vS+x402+Mf_ZEece>d+~2=F zov0K;F1tb$8NSh}nsKM)#~s<+Ana~^wmZ2a174ThAeY$KFbkcY#sY-e@vQ_Q2`Ph< z9u8?ag?_XZNwXPc+*<8#=Z_$jb=Q`Wo|O+tO~JfH)TzhIRbNerzfIPNskOOWyn97C z4egyaS#>SMGFC6MoKgolTUE9`i^c)d}xNJ1ji22$UOs!BeBX&3ZIf7zr3 z5{U3)1-|$Cjx$Bbm~EiBmx}Npc8n=EY`D&9-2m<)c3nj>P_;cE)XqL-onCjblKb z71UI+)n!gCB%{O)%Tv$`zY@%#J8Y zB}o{i@R)k;Vx8#F@@*w`f==)AJMbaFVMs(sA80>%nc{di<^0_|=i2dnttYBepzLm` z!oO_(Fe-SqPzQruN1vUZ$l2+Anzu^v$5xM1kv+|~pSM!C69ce)innqe+doaSzWC^| ze*Kym{BYC0^z`zTMlaT%C%jhB`yO!dW%+~}Q5g+2mFTn1v;8gWY8x+@k)t4Eg-DDq z+Pb)wOXdY1CZQ3b)gj-EIVgAPLW#GzBL**A8dw?kY`A2b3-x)1N-TWRELJULigq8n z61Ob2T-Py%&J~grtJG3-X>$DmIEF6!#{?j_>yARi1@GZZen$ z6AS@q=m|JOI#8o*Y6wcc^5HVTxW8P1UGD#)-+rkLejQM7?i(Hc&N49hl7!Z7`zXm! zmlDB?oJxLS&0RRI6{HI#X~#`Grw6NND0G=V#c{;GUA>T!X~u!9&=&0ynH;UWUp9w( zsrCd4oWIY)y@9pz)BE!?bXmw=jNN1}CS<`3T}9XnD~3}1Rrc5Xc(t^g+!iWc%|JHW zajZAlftzPF2vB56H*kT+;yi&F>#7V)J6_SmH zULvEvr@(FFK#!O@P7K}5@9bg=Wf5Q!TIZ!7BZCc}rO^hVL&jdVQ~RR6Ctj6YDZ2Qp z#{K;KxU_$fi?M{>&pV{TqTqazvaY@E3@;{AH}BsWki- zw+qcbXaDzHAV?0@dTmrBZO1CHKM@{WzStP|a08cnX#?r>`hdhL999=)JE zgQ*}EV#5&uhMIZx4eSgX-eRR@zv)IPG)7{~HqTp_U@_Ewn7{oMa`p?CD`P+4#3(H-)u{EBbj8K)F_Dy{*e*F&HJ9ABz zSVmJ=;JMI8B9KMcE`o#x-2aM#$$>P`(YX$ucq6!QQQLlf3k07;xVubc#YXgrg`gYi6^fx=G+EU6DCVII+?mM%=-)wt3?QI{j zyr6BTR1XqhnNs^0#@XcfoHwsnywZFN&|I&@G zlUbx4>qoW+-w4+i({*^t?cHZ-><2BiNi19_hV$BbT~mkPC}`aHtXniT^B*q*=24|G z7x*h8UYNpo(=bl3t=nUT<{!DhrIy#?Z!|-FR*F_ALRkgCxGOqxiXP<_d7cry7m{&X zMoR#t0?TbY+EYiOB0Plfhd|u+X2H)WINHFoi#HQ~>$-FYYW7ky zY@tFX)1q2y^d63u zLMLr>XTXMpM~bxql7;htWhgER43VFkIY&emC$WIr?Yie^gjBaj7|%B*?a)j~H)&bf z0ms$|SzV;`y%)<~x!`D$PY{_O)PxnpkOk>y4O&l~5@x5nd^Vt1ek=oqNf$kqS@()P zhby9KT+DJRxQ-fQ^UD^FxxiNlA*6kq9(saLG)et$_x+Vn=h#Ki^cyxy?TWh{Y_)y$ z{(J>yr}uDMqW)?3ihgr4SNc3vk5hn=zb%WJypsBe65IMxZLsshvSfayJUO*s7%~>x|ORfMy6Yo&c*Hs0mtoBJaA~{PEw7zPGsk>Ub#31 zLC`BCU}0NB`i>wv(1Cj6DYUnEuK4{p^=Mdj72ip%BeCeso&SzIXO_jVoM-La&ku<~ z!*t&JS1ed?U7}eH<$4e+t5B2=EC#ZgyrwWg+3E(^Z7*1ewwE0=0p4c}bTCJXdSdZm zJ9amn1x>hwF+u}zXJyb}44m}Dc;@%{*Ij;PuDKe%STM~*txnqpgvY$~67{M0op9<} zd(9}+qMv)lMsY$zWs+IFVA>kXckuZZr!9sZgiwhDu&{ydg0jI{yWJD>6R-jC$7##hY~ooe<*zb!-9=`z*$UanHfWDU)yvsL}S z3mqShoXbD~Ir#2G9Oen~y4-$d;E^7L{NyN-urZ?63zn#;V@IVtO@(gC(mB`7{ZIXyXF(WdsG0#P!Zz|`J#j=}@lA22YB)_|jJU7Tx1Fya$%;+|^Anx)0 zsa9>?`w^WmvXzWh02|(%*5yVJX7TVNw=^zYa%?#*H$`@ua}(aZCy|trE{WMD>!z}nqf8>j`w{d z4m!Cm@Wi^^q;AcRbXU_H>$lOr{_1XR_t^%%m8jT>L;J`p54ge#)Nwp%se`XA_kZl zViZ`LK<|Bpmj|29pWIG%xUjB8?0*xOVO*l=OYYMZWT)e`_ptVYfwo_jRtIj zLEUU}8C-4O+2$E_qoZ2d?~cNci*j8;<0ekIkb19DH+#Y@pm8C-H)PB%t$~&Om$0+pD(^A6 zdcuqBcDMXm%Rg~O>m0%7{mbAPFC{g#Sf`>QgL=n$k;+CmA?`WqBRF2NyI7SZz2#?| z8q-LC*_4-Ql|!xn=f#IcU3nNj%wCs6Rq#`(LqCAD^_jK`F-xfJ7 zD>`##5ZT?P!O8oidP%elu5f-AN0Lk2#XNmqzcZay?4Me*>)7uQvHlc04xVJ?c#$yZ zR{aGoU@V+aS-k*mAUYFTC+~C9k3*_T?PPeczkK9|)!q;Z(#T>&F#hKM#kh4M?ZLra zfmX#@(bqpDH1_WHngJC~_|OZQk?=9U5t6(-b&f$TXR_cBTtUs3Z27x~_YEh4cZ8Uc zRYj-ix_=A=q|OU@>Z16w!p~k z=o8E9i?#@D&fvOm;P+!%>1Aj)-B;#wFVHa9r3}H5{CFsaKobjDgEI!M3}-F-TQ*Vt zUCkH!GYKDZk;WLe*A|}U7t7G&;0Az|i@0de+v>bPUBdV%_XG`YtXvDqyXKEbH4ZvT zvgw+c3XC2M*mq^y6C1CBWnS)Cyq24D9Y9gjQrq8m!f+|p7(h$>C@!W7wZv)N3-*^{ z{dvOP{qn83Qv5?kgQ5GGa{62}sU|ze^~2A8LVB&M{aIC(7}tF3bknWL^P}RWT;3Zi zp^%_!g7e$0&VkEEwHon3fMIcs*yA4SYEs6uzkV=b_^HzkG8U~HZPQ?xI2uK4ta93U z_?W<$*WbPbkYw=u(+oz^9#6OlvlCAr#q~N}v5gocH*Nx9bBVq|w!`NJ;@)os-?CV! z2D+!pl~}^TxG^OM?iV}bu`fb?GY#T);?jKAlw~BCt6q)4pH4w9UfZoIg_pfHQGMo^ z@;<9em0yq-GxvLIndEq(<{4r$SxB0on?CiTGsk-6_iH8Z$k&V4@p+Z~r3&5%n8=<0 z{LA-`M)r%IOJ93C~P_18|iBGS2~0vQP&B`zxZb!dI6{UXwjE z5#vKy1R8(H8W`}HL;Crl1h;pUQazsB)-^KXZVTy!HRbF>Wp{u9rgEtb>7h|Ne8&F!@lu~RUH-r`Xzg`x$>DdwLfe8~ zbRJ!4LdQ96Pnw+?ouw=+=+gPqyV|D3B$07^xYAfAgy7OVIk&n}oaQsx)GS263b$CVL|HdfldK`A9P3dlu4ZyHgZ>ZMkJ=AlJkx?4j@f!20 zzl0;0{1aB69_q>m#Q0hW@V0g?K`f_JQNiX_7C}5@Zm%eM&{k*L&FNgnon3pwsheYC zhTOkri~Y}MFI{8><`yukw(fLL*8b*5$OV6VlRBnjVfe>d=6uk(3AaHx9{s!i#cTNh z-5GZ^bSarRjyX@45pt`Lzm`G&tMURJf8x7&y-#yo8eRv-T+<#dB(HnC9Xb?2P6S8 z0d8i8%}jh8OwaYdUJ3NCTb8`2-%7-kWJKg2m?X_=3#Jnl&Le zjuxISaQAG)3I?I3`#LpW_(`nrMR(^cCB^vR4?!X`;FurrynJC1DzcE-D`Y{MzQ|6zF8IX{V@gz??8P-yxNT7 z9=;LsiVl;x^w^J-C?2IazJ1amcFJhOHe%j=Csn-Y*$t&#gUa83<qlF2<7d^?T3ix%$cRU?HiO$35d2Vz5WF<(AX;c@i1& z^cIlRpEjftshCeLsp}4l!(E3xax}hOorREH@s-%rLLNJzb^Xr6Z_6n%P}lFN<_N))jOQ#VC+9hT2`$ z7a~D%shrQpZp$CiFJIbS z?$d+qjNk7rm-i8)M65SwIjjo3eUb;h-eP*}cv|HR2)Dq`?=3B*VYG}_0{Sfk zXz-BP&jlVfk-ES0qKVEu?;f@%7dk0tQZ7Nm#_=?4J zL9rA<<51P1L;p*-q^GmeSPqTxckXl+mXh6jV~%vOZj+?>bGY1(R2+;~h(IZNp!uZW zdpX`y{dyuMe>8Jqt5e%fa(=<%fy=u-7C0p>dpERZ6jS=O1mPjF+UJGE0c!|7_qOpp z$K*DBmvL0j7-wDG_{mQAqfgdy zd&)Rl%VQ%ip;(=zwX}>>u7a>e=BH~j2!lrP7fV9S8Xo!a zr%Xl~@NthT9-wWUXX%N0GkhTh$t=IBHlBskDAD{_d^cOE7az%U!s<|+r}E_DZt?+% zklU_fI70qs^`)PEW`&^Eug0_*(aVS8_aiQ~J0BU(^Qtx6o(bJ^trJP9b|H0fv-gRf zglBN}7q~mt0%dZ>dEtsGO}UOYLR!)P@Ovh2nA|S@eH87PM#v4*Iv<&M?fJY*GE%gF zAo6}7GZhD2N>;*Sl ztWsa&Gk*)M9Ca}gk6NR_M&Pa$rO*1`?s4DFx;jqVYv-MUzSrY|T}8XJ3Pf`_i{cJB zj$cJYek8l~)2&XPky9BoN<6mDj!nz2wJ&{OHNRYf-Q}5qrjz~5>tTu3Vq4@?DPVJW zvwy9-uEKP-Q%1>xMNIac1BtuIC>-}A0?X4gD)s{ z^|8&3H20#X!mP?JYHFAY_o!X%SWE%G1DbE(&#}F*`W4n6tma#|++pmyqqSK6^k=gi zT3BfK3V2<^%-HFK(2SExG`OHKR(XWPpXhixTy9JwCpR+6Tof{~j!&Z&jc0_`yTiud ze?m&|54rW!q;1hvdSR zHRNGMrZ{l8{)j4L9m=r5gE4ECxv}a;{$Z=%4D+*BzGKoKu~N?S>JhPSW)D>+UQv*9 zbF>uCF_jAy&B0LO*TNNB|1|QOH1kLDL8MYvPxF#fZP{bAuMS>f*l;Pr@;l_8;zd|a z?1ZP2@H_|SoxO8w#W@d##d$B&tu{}8@d&069;`C{^&RDEB0a;f)~@!vLX+}U0stO>3Au{Mwh!UQx8)9%IQsfp z2HlqqAE4~ICzp`oqKR(>T_C@L)?Z18eLfx;PT=|xai@;0)82S+~BeUe0O}&F`E2I9W<+(=U5u_-|Nys=NC;#(4X!P$^cWy1EVxVGIRP zxZJo5#9Pc3lfd1$_v`B%-%71a{k|Nbh`XlQTQBl$Qxuk!jidG?t-^Qera-G$^lM+h_*<1EDAF!zOegw>PYA-*A%3v?F!6 z4m$j21grK#8Bslhp2S;xub@pK#BWxA=}xrBBICcAkqP7i2Kd>$P?6BfU8)#aoxsq#kn(2e2e1BGipUST}F{PH$JzxkjJ7 zJbMR}qZNF=@RV-PIo=hEBTRUh46hi%WToz9b0mPJl+m$9!d+CBl36w&%H=6{?cV$2 zm-5R9=NlFltH-1f$XjpYAk@}_ix&e=TdxhqSQg6m2h@+cwF4w4lm^{{F10EV!cV*? z4J)nP9qw(hl;T%4BP)f=6|OPoBu;tKR4Wt$}o_Jap8AZjwmFSe2`{i7A6rY zO%B(TowoI%jKm$(_?wEY;tSh@F;+e1LYzw>;)p*Mx(lv%CV%r)TcC|2?ujuxUGesL zD#lwo%a*QxLNs&Dt~BRrJU9q=97g)tika2wX#13j;c?rX)+f9SEVq`^J$5JL;w9>4 zF@4n;UevBSx#@|>4q4=iJH~_Krhc*lzp|Z84)>^Z7>gqzNyX3$DDZ=lWI^ ztCJp``{>WB2xy6kVt-Q@nETD$L6tJYt!Qs18>5{hA%8Md(bm56^#(uFP!)kfoP6i@R!N*hBvz;q#}3BS72E z+(8x6F{ILN3HQi>;&=Ry!=1j28$WK ze)sNOwp%QBBaVN9#q3wJ|1gEr@{t5b&D)?1zWE593eAz6}=(-H#xJ4q;39$7>#a~qR%t>>Ew>X z2HIoQ9kqDM0ZZ+d4uaVK6b5>23x^OVBoxEDRYWL9EONK-T@RLCAN~@8hpzSv6KJFM zmC7>kGv+gU0Yv?qH)Xuhi9${u&oc>=6XZ0jZD@a$%aYMZKJarQ-_MU|4r8QSH^t+3 zv{HlZgUPGsq9>m+9h9W4p5?s=8Wt9hFJwBrS0DxgH_Np+k#7c9#}+BKDv+IfI39 zvn8>sHO{6nQJIF24c(yZu01D090_5q9XE|6htaABUCa%gcJ`X`G-hR{KoH12oxx*- zSsAJ&V5BGAs?&aFHLbmt1!(sE0R+i*pO8Pqx{ltfN}Y>O{mR|DO@Nu}bJ15)r>8-A zTf%aN^SMU?(RHG`0>;r&bff_ncT^c08Eggv6c@aat$HJLA;*7YmzNMqaX-ylD;T0+H_aHK42d&HO82Zx{J;ykkkI2sJ zP(E^g7ZKYwg-GthRYHJ_BjWgFc_vu11Jv~P3VrG=p>i*sF+gS(G zK&q8!uQ|jE$*kXQnEM6O9R7Dtq`7!}%)yz)Xvb&fNB0E>L}U7P`jAEltP7r_5Icly z@L)?5E;18f_*c~7~6f9r*(H=xY3?%6>-n&bxL%oZ~JAsbVO~H4b6EB9sz*Fw*BXPQ_<~g=R`K2 z0Yr59!K2Fd$^-;#USHVZf(f8;kb;b(uJJ5x-iO~B@Bs)I0d)D_8!x+k0`fU*ADGQ%(IjiXx~~^M1n2Xu{n>mku_1}y%g9W zL?s3=ojer4Y~Sfd+Jn563pGm5%Eh?9Xr7Xtr|m+-hYFW$8_Qtf5Sfb`0P*VTNBin{ zz7!nC^w!#`k1i@3ezohP6yJAw^hjI2@7Ghr8Z5bVI6s>nqdo^1nY26`4n<`bm% z3^Q^>nU?Ku0Potlczw!lyI38FaaP5UOj~R8_UvKZN$5N^qjvm$MXFI^0Q-Bi*|hT< zb}6CRWmt)K)E$87a^U0EE~`0=HsAjFz1U32#f76pqBLI-$cn!FQ(yj3z?;!A~e1rvjag-BG-22 zzQ-W3>yFK=YZ0g0cPMOxDEhC@JVn1l<@!BwuU+1$&zs~z;3m@j>VwQKi&e|v3YF?M zZYnJx_H)1O1puT!uKqVu)u&GO z3ecWPLXdLD4TYosY?7bq)W@xgwEFAcy$%t3@OW~9{rQqmhWnt(s?UYW{pCw<~48GHWWEI}CGx`8)0h{-_>FW9y*Ps#z7f+~A;YMOLrAPyS;fN2^tN7y*snp2*4L3Q^GgPS*7mK;RV=cWi$9 z&xrjVj+tV9v2JFrh4#RZ^nHD+)oM4ZImc2ZmMHh3$s%bh=UTrON5|~ft%P^O$@2D1 zyjitTU^+)b4J-O+7az4wZ0}vP#YC}~X-{vj@z)DAPW!p<77*>7gV&|j`GCr$|B6QJkR65YMg1TBW?={0#3U(o9k~s8a>aL!@-&U{%ZM= z!=Gzs5l^|=^a|5AF0N}+clOKWmCR7fH-ds{`dbRlp`?dJcYkllQfra+5|7W2!V7{a zol?1OfI1&)C_hlpV#mncWS&#|I$Fog=JO|R+_B#g_rn4R5x;7B` z-ZE(#yJy+_`f2+4W13L^+Y5j1_iFFNTwHnOoI;#MKu) ze#MUvFSK>(8pj4+$u_T-5}%yn{dikUlyBXJg6q{&y-~>n+{6#=8~=?4#}*Y0+n8p> zO8n;P>3hQSM2KRw)9DZ!Ih?|PMKj&_&*yu96@Ckk*td&4PA^XPJ#>Ghc!99y#j#cjvfy)S1U1g`_DRJz!ousd&n?JAxWc&|TKy2j43v z#otSO3VlC~TXZ5A^Vz#xMeW1w24fddvR9r(`X#z+`BWKB5)3hxd2zP#WipKCp-A)t zYDjJD!NM;FrHuPCvZD71+tnOixfir#Z)jl8C7_(dI2Q@!Hw!KDlXr^BFE)SF2-93h zvOlqNL`K@Q4?#~Tuq5@BCufo`x9jPVxIQ{PHDv-Pq>fU9QZyJ2>x^-rw7cW6^g8dv<)wR2-{diGZ}Sp9}83tFNUabCk{UK);Tz*9Tp7yA~2@n(|` z1szWMm(Y#XZ>-s}*A6sNX_6xuh`GItw2DRANK1`QuR%-wWZqY{f;(~7zc|z!RMiDx znT3S{tAT^2{;B%t8byksmAa;pYasz2yV3g+Re{kb%DC_`)#NbWDrKXQJ%GCCBc!;a z;birUnNR6mA_%C%U!Y#Wn(|-nNAQ)_;&~tj+#{&JSwOt!oZ5pc8ugLXiGWSn)nb56 zgoZ?NGK&acN$wQ==4@DEPys#v^gvTe#? zDCb2;%v6!37S(SP5c1y@hI(0ed$N*U#b?Xo!> z=gWlD^(j>roElzl&J!kfNp);wMkg|cfgzJKaeZLbYmLEe5wFY+)sZF%FkXBf_NboB zCyv5leuwW2x{JmT3*a8=np$xNTUr$>*$l-(&&Q9mxf|1{Eg}Dw4cI)lwVY^ zxm$mcvX&{-EY`-D)GsUGKGR!MF5@X|X8rBM+Hv}OJruMEW8?`n^%{M+GS`0p)nB&+ zcn?#BsTSS~6f7FJY+F?60~e>TBZo8Stpw)d(%laebS?4K=vg3TbF`dW6z(b6~v0 z-=|$f(i3urFZbaVPxO9EHEq_EArOF}3w>>rJ8JTArLgOm3BadF)v=uY+HNWh*YBPd zBR@w;-dS_0Hfa)Peht}j#r;)KSd@1uQnITlf4RY!TR~+V5NxT6llLrF@Tyc37Xu>* zFo(!)E#=&JtgCO(aOPB@mh7^ONu7jdNzG&G>>30F@)nKGHZdQz2Q?}qTK);|;y?dj ziKs9}Lai}N|Jgl!^j%e&XVR(OQEV~G9zN@kxFFUfBL&?lIUfn#>XZ~g0%-S{8v|eS< zW$gU?)d+cqVrtI#D!QnEnh*A|a!LAw9hb)JkO7y5v%o7%bv4xn4KdEr(*vOwwxU=< zp0UITU7{VbNZg1h&IoY^BU@V(8X6i-y9EvF9bW=Byygn8Jo9;K+MJ(Iu_k6Y272<= z4>@6wvRCq^cnPOaXR>Ub7;bnWx{A_@<>Af@i=`152zMupKc_1rH}-oy_XXqvXqvY_ zSsl(n+WM#i=f^r)uzvncTvcG$VbSX$B7}FHI0l zBj^3x@}W!UtoEwrT+vUKNBx`5hLc&kCnqsM176H0BNGBKbS7$YD}vq+Mu0{{MN3O2 zOL&sS-}!2bt|i(pEOMMBN39BhLO6o1;?&u@CTgGS%eTx>r2T0Xv2uEyK}TFvRjM|h zXT;pq91RFhP33@#U`p|w;SY=Fu}uWllW_hm|D!O2R&Opq;RQ`dNLcbV zicH6Pa;hu;6+*YSHPKw8+or?*FWR3q8U?z~PG@JOa#p;$))(lbEgwE-67Dg zPF0&2!RKtFARz_E#i4rG%hqB@%B%b7=vH8Zh}xV)I3VBtTIx4^Z;qI2wk#gi3NF*V z^_68=N+jfIR`-15ZwF~3kt3j7m6Vamb32$p@{zV8iXqb>_&Jr9ii9pXrT?W6 z`W$H@HLaJX$fPHL20iOX+>qHcTee-Fgum6^>gmy<2k`I*Ao|5dP|x@2%1*qVM;HbH zk1=PUw7Wcd7Y#NoHC0Sm8LhCeaFUbQ5P%%^sk7gFfgUOc18`n6TqvT6Osa?d?&Ieb zv8!;vHh%f*6wUHOtKhfE_RZ^bOGZ9t;??%o)5G7pT7>O@#=kml{oIut`e}EjKL`fyl%2-(aXzl-$iO_ z4o@|?l#2o)ILF&lV~tWxrdgLi9i%VwwFC2onV8hbnxT%wJwgTW!@Tzx^K=j;fFgM+ z=AjD&TtqM2Zw3Yi`QiB3z_Nrya!OSI{Tut`%Bg|^z5|&hx2;Xsd?Y0(Q;5n?=**)T zK~oEl8UP(h6o5;8YL%x5$q6$Zcv}m@ML+TrU{y-qXK~?eD+OLOQM(^2CkV7 zKLITq`08FV3dOHB;1>v^zK#w7$U>X#8+VlnP)CkkO&0~_i-tpoz@vqO25@OyHqzhz zi9-eN>P1RR^b~>xoy*Vv?40uo^azk@_P(NLWMp*Q8cNioWk@9lokAv3HB}v91%-s} z(0p>l!>}LoH$+Ip>TbCT-iB!f0w2A+xaby4^7&UGsN3H{I~MW2eE*mm?Iay+$rdH6 z{uMeua2E(Gy5emtdKOryjj3t0b_iQ@HyEk_ z_fib0h`|{eeIFL4WVEV6n%pNaJ*lJ^xJXqXCblTLuo56rGJd9#MkEl2?wFgye<4+v z$d$sm$u<#ui-Prf?0>KTVs-ev`6ZH?V7Q+KEd%jihD&bl>nr%uqMk{&K2ml4F(ZnM zKj5lhK2aqIw6O-wsMbJdJULJAiTD>7u{o!>@5_oS4l5vxEHZNb)}(UNMpavhnCkB8 zVg+P{M1r2^^z`)3F695qvZ#r&f!Am%G!G4ffnJ!?1@E@(CG+XblY6gsg#qG2jQAAH zA7NxV!6s8`LnW_<7uL773VuZ3ZTy9q5Ra79KUV}YYLS&+NAQ}8mmY2aqC2+}S!gAq zMJFPPk&4DO20i^OS6Z5g4z+7^-$f>st<>qb10h|wQ-U9bSv7Gh%^oaps6+^w3R0N> zc_OGAf6dH;1U882RG}i^qNrIq{HR7q6`AyXvTm#r?2NI+R`4U;e~8x`^mlLcd*IeA z(ca{T$RTwKPE9doo)yK(XI%Uq2pD5@> z(V23M_4l}=!@jKL$zsMts{T|R!Elm;O<3|EI z%RK#N(8Ib;Br}9ehi*h6;yVrO3xC4E!26&GZ*cB|4uK$=Vfo6>&+l)AemW@)7gr+W zmm#R-^WtAo_5lL7xfp!fei4}X%MfYM^4bF+aRJYF5e|udrbFT!fL$ycG(gM&JduxX z@bK^k1%QNNEO_?cx~w zk-!26b7v&A+t32>V0n4@u6-Ude19;-gBk)7i^VuoJ)HVHO^fX;zc>uZONLVJ2$qNEe9dvQLq|(CDlyGETw2Q+8b$k;nuSmC4)E1-tjI zp7baa`-=})rLC1vXTO(qN{t87zMrtXd)cLJM>5Scu>TCeXPbC(^hg82|F%JGZn{6G zP8--(Ne&Ma$FfjOF9zsXk#-jTMQcIX=tUuEY?8yv*Dm_k`KXB=zkJpQYv>9J{LftY zMb`fx9KtzaZeEuNg{4{X(t#xW01a&0>w#iR1tvVC7RJ2Kp%h`NjC`=uxgy&pa0C>H zutS>6u|Y}q-?ZgQW`KpEcbPJlg_>6fqPVur)exWn1S?HIwccg*z=4ev56sD39>b^{ zaJ|Io$><^r4JpJ4LVth$5H#W-j(zp4${V3w89hg%e)&M--YNM5gpnjWiv{RJks`H# z{Ll7fYX_5{qfptv%DSyOA4^Z1WYtao#{sZ>3G}>JxpU;~wSFzvNb<;}BjmE(8|8(4 zEJ^uA=sID#?0>*+GTgzcoNhAk_n=D-U&CsGH`!ew<`&pN=>YtmGgz<0M`+sHGaO3&MGNmeutGH)P$w834}H1LLG> ze}&}lD;0qsY&qZ75#^kO%DSehN#yY5ELH?X9_{y&hxvg^FXuu-VO}io zsDQKoDMrvXjEo;`gYHx%*b-28`<0ZbBl$6BE$@!0_rmCs~ zIEJ_FJL6gLUKiVE0Rnt{XOO~Km&%anXyn7g!}sI9jar~htI>Vbh5vR$YftsKLZtu0 zJ0xL_>!G9Zy?_;6HlH5od|ZXDI;m~BI~Ve}2eQxOJBCLbSh;>>H)}^zXll(79|J(| zQw}T>18L!YlYj`{)d2gORNaS_I5nAG9mSk)xY1^{_jF6+$?Bk#h%R&J;(O)I5~GLj z#{L>=Y$!dgZWHHmK-)Wy2fQRSaN~{w?R-oDr47D-J7aqUpu3VD{6;kaf_%P|R@D-m zueU)3^5yYzx`Q|HcOKhIKa_?8Pa@m%Y~#)yKP?5D47R7}l~-lamvzO7^S2)6-2xpslcWn=jwX;S5N_^8kNQ6W%!wWiQ+W z;Ij@53W8eAFD+#t;IU`C9-RyY*J?68VB4sQxXLeI&N{OPcd+#Je&1npA)msEi)n%1 z>S)1iBP=WoIvit1;WDLJY<_-|d$QE@+Ro0-(#mSfOPv!6SmO7FK&$o^1KnS}7*Hm# zxOPCHAhx7{Ru<3^i5VJ_0(yy&1Spp`6ToE>?7IWw^ICZIh8h%G&uajE;y%i?ZKeRv zMT7gqi#`Q7kY4Mp0E+DMPaS$tb zsP{#efD(4iTL9+}pU3`(V@B=e5RT+(vjJpw#Wj#rMs7we)P*npDSejK|ccVIl!`n)Ihi|1s-#*1dlDHtB|9DmoAzEukz)w zX!9&`iEtyp(J79GiIkhVGe0wvRD_Tt4W5W961Cl+0g+sopY$SXDlbu!-tfE@9h_7w z3Snv}dMTuw_tjm&txtQ&0}(uIw7Rkq+haLpgi-hBxH?n}<^sSwNJruo1SG-X+_y7LSoH8J67x1;Nb%wwPZxB1XurJVpr9dbb)$vA}`H>cJzonZk zq3DOrqK4ESyo*Olvi5iLsaUfRFk@fgdHc({Dab4KU-!bR);i&Eo@kQ(q>A3qLVwzp zeOD2>B-X35^{3uLUDhss<}Mn#pY*sdJq2%9uOEGS`0q|D$npC+GcpUK^@ct^(?n#}5)cJ5;R@NMq*o7O(5g5UXSzDD@I`&9c*4n*RZ|PZRzZcuPa*Qb??GGq zsiXCG(mFJdp;Q$ZM*dkg@s1BH&zW+a6jl4{ak=!ppVU%xi%2#$I(2;=V)_3{Pv37j zS#G{Hs4o3wKuNR$KyzBfj^rtP_<4~(4@FZHkmx%Vsq%YFd#m~0Lz4Qmh!+;1i?WD% zfPKYZutv)CYmB$4RJypiBtVgDCh*2w%5apYTYOS~7g_i~vqY?wWB`bbcmI}P0h}&4 z@_Tn(mDGSaWOcagS}O@&2RlCS(qWHQqY51Y8R>h~td(cnq))xt&*re^ot_~wrkee# zGEGONfUK>+536PDRr6G!=3N`9jwmNA>grYhmDbyU-73xOSIq$>w5Q5qzL4i`f9_VT z;qQ3-F6~3^5NyQU)Hi$2pRX@|?zYCp#H;}#Kx)Ob$MfR$E6LKIKPlMQR41--F2I#l z6c?6RPz3rqk=kYz>M=or_ucr*dcX-_4b=U%JaC?^=7t5U=($L#c) z!(pu^ueJutWz25qC!WsRldN1Z&SjCek1Ai*nVv9nKc>ZFP)cV5CUf={w*`V12TK=f zJJ!Hy3GOr9+3jxGvz+9KY9&N z3#yEDjg|3p+XDAw=*b2|IFIDXURbGDbKRAi-qD{Xku&H5*_TD6LM+WCeg~L5sA}GR z_7C1o=W*BwIMjzt`ThaVzl4gapcw{+D&M~V(a$GE@o}{O`WcAA|KOML3wCyZEw7P6Bxl|goMgh)x&!-Kupx{6< zbdn%qiy4!P!7PmT6QA+r6x4nDqTUiN)5p~NV)OG7G~S^dK3}~*<^TR|o8P2g@~#dBlj~n~kia^so3yqhYAXJLIJ6Sv*me>setu@Cgd(;I8_U6!6;aso)NDiYE|J zOd&yQN(D~rR`OhSP2oL5kan|aIZNHYkE{3pG>@o_p6GCZgTz=sjfc#fIlRyKAP}X+ zw8nOD`axng>lVsq%pU0(U4}@I9Eq5n;0XEgLK;Jn6ba(%w)5F@`GuH03<;;o?LZS_ zLi~-GD0(D8(2>QA(eU6_CmI{l^3~JV_iM=mdD#MuduWFrUH-MZ^~9CXJNL-r&*sgn zNB6N4@Y+kTv>-j6sFY5-5#B#0|5<``WGx17${PiwfW&9{PvuNDCyeP^j3J@gLT`pD$tCh=1!z<;^2~ z9}IzfNT99z@Pso{;YI_x8O)FF_h({<)t7hw=XGhq*w0==O2(NPofO`Ww`Y-WIjH$P zj%_o!*lWqi5VYZfR+TIJ9EyVN>5dGX%KD{p>_m@O9f=-hh}9tvXKVbJVf858xjdnG zrK|*_eP~XPtUFeti+4MtFEgGoMlYViC@JR zZ~vM=T!^hc4&#uXHP3HXdZrVAevN@I!2%x^AT3DryK-8x?v$m)!3;9h?-8d_Z6bAf zIIm93iH%W?r~6hBos}4>O>!T%+Foa-#t+LlKCsz`~pPi;J_V9^skX08%&6Q|2mFi^F!C5`cY<6G?}JJ_175nN+Z3qy+1*>cGT`*Jp~ z5m${$Jr2)9gV)WJehZholNE%8BWaP<3DV>hhJVcHoi=WBOq%3&mnsO^%?7Zy2;}@# zh&+y$qz~tuP9N_$-YNZniQVT?-3+(W#AI{l>x)H0g!o1WWRm5YK@y&nZ*W1BNNK6f zPZt$;A5OCm3uZ)`j2(lcxF7F*3T+N%BO)esq>3b|kS9vQwz5V$@+q2Va+3a6YCCHb z5&_-?voq@>w5Si#HQ0kHxq67Mhx201k;fdx@R-yJp^6LvGF>o;)3?S_m+N^EtTvM^ z*<3KUd5XzN?-QtrrBO++$|Fg*jbP+jwWNg_d{&t`@AFACpQ~{1&RcMPRz~g)0T-xAv-hPGqrrO!yjYr5UoCZ@ho3H>Y7XYz=)5@iD!>osYz0@uz*j z|BOnPODgCa=&{NYbF#yNg>m%iA}j#%+0t+=t0>ZP9`Xs|Vni5yJ%L4|6u5(E%4pao zSOo|x)lw;S2L3^bb#S0Z%JujP*)W1!bgUEu-cQ%)V#&)e7d*DQ8}v_unK(}oH{H|2 zT5KjA2r)m{*~Kx08fVe-6|>-&7V1R@eG6C}=Ji_cuG7~=IlhgFVF(=^q=MKJk-ttI zG+)hD3_GUZa~Izw=>q(G&8Pk^&)tq&`(`L4Y_G7Sl|HLTYSA0MZF1h078QNPZKoff zTxnq3IdaNXN`-mk`7Vt@`gX_f@!}l@)8mEkbLy4m_03H`;J`%BbKRQ^(rvKk8b(dk zdfBm*=!uaAb=KtO%4xC7i`PciXtiCRch9QVX|bd#9Lo$PZf-E0IHX#ayevL53`^s1IQC89w#Q|+ z7{c5l!2fJ+?>026z7EJ=Zyyfd_C&o!uB92*`g-z3QL@ej7+5?$`^+H`Wz2~#k(14= z?b)L4?p{FiqOg|4q)T*6OAG^~u7d#BQQ?6jD7m!3)2(0M6~Yw*b514RsavbSu* zJqUiQus-nSnYe> zarx`Dd%9PW+XBF*$KEo=M-B_A+3V%*&$~D@ZM^~~Eg=M4*4dU5xf5dluG;aQVTo<8 zxSl^sNg_jh69UW~%GlDl?Fbr;I-zTizTClrnIXd1O05ucDebV_Z6hac-2;dVSFpDS7!X70dCk2V*3KmFGv~*u6jdORk7P zv#bL|d?)Jdblq@lyF$g_N&IpUA)x{0FFwiX_=w+i?YMA4NSHal=r%4)4B4OdfPfb! z*902nK6p~!K#dZ$lJ#8qovKmUug!kL?sZ2Ceask7r=1dyZB~TzA1d+pQF=oj&{U`c zK7P2O^y`C6l6ZUUhDcUY^#o$P)}zSfvm8bpJzKnH+WlK!s!x#?0o(A{hWLTu1DXeF zD1|rZT|}$el0O8P63mFDmGOg=?0)AOw^FZ5x(?X1gFHTJ=FBk&Yd2PdEAQV(8=>6F zQ{`Kk+%&4(uz)U+S{^z7;hz;x+>7X`hCuTVWde(W1>6sdt($KSW?A%Pe55$hP-htR zvC8@VqOOG&O8F;LrE>va`k6|T+`a@9{2(Xzl)qufXRu~JGm6v@2%Jqc+8nvBAeSO z70Siivhl(BagBOLApoeduqvBywIR#sX8zp zi^OuZ&%1zH7>?TtlYhtr=XEbC@YfJxUvd;0-!H&%`c<5gr>`lKYl4{3_iO`p#ruG1 zs}vwDnpVhoM#&ysu>MRam{L7AsRLyU4VV#KTSfbVMIA`v{|?`dsxp!(So9sj;leLu zL%*xUq0ZQ!pCjFc!g8_LxRJGmUH@c@891G)-0pZA%nO7h-tI618&jK1ToEt^T!bg< zyi764x_Ocpofbehf-wi_sR<-YR4R%ERM9uWCMWWtQ!4KR&If6VbsH)=KaL(SKXRZw zM4H!QLYBz?vrsnVr&(NT8QniKF`8k50x+tUW3WFU$-J+Ulx)uAkBh|D>0a73^uL2` za)wQOb(v57Sew~U)+3@7{U1g3Mu7SFZkn%b|82EAIzo`>e2v+(7?)3aq@~YS=Vv|{ zDHIlm5{(i}KPXPn9>BaWw`>zyI`HdBZ?IeIKx)0c-v$KBE^k4|!sqMI5^mW3e*BHPi z{G>K66KM8B+k-ckp6F}2l4RY%({XWRjuc>)R^=f_B@vvvg0oH&yDdU|KiaJghJX!* zFxoT0`6KbR$Vyh}jp_V85jcg>L>>dBV+l$sCB3A)hQ8C~>7D*|JNW)8i^C#rNQyJh zZnce=NQYMZ}Ia3fHTnmu!n9H8C8sg5nLP5eg$dI!2`ToFqgxhYx zXnQ0T0RcgU%NyL|Dh}7Uh6VisjuyCDZdQC!xb4!SxTniLVzq={j`FN(U=%O>vN8QP z@bv}TFr4#3TlI4i`d}QaBKl^3yq4h=E~7R&xKN4pM&XS93m>tAf*B|!;&Wchix;j5 zC|gz?~k)j%svO(>fh5fLmm1q$+ip zljIEJfMv6($mDZ@d&~X_!C(?hHqN*^oDNEEoew04Tn}ax5$%xlqju-2P4j&3&TlWq zMVtT`*5mDFe6ePE8s_rjcX{Js*RM3nnQMSK*&0dI4HvF%Rs&ubUgg%*MLA5yT(RN?cR7@?lNq#70XK99X~1Jnk5`FW!53a9lQNxO zaVjSPcEiAX??Hr|r~8gK;n0na_yf#Pz;?SArignKFs*jtJaYI}Q#q2%l7)FzYd)&hwX@RdlQYRjdui1VIByGjgbec^b&{d8_UKwt zf||a4toa0WQ6m4HHYi^lhLoURCUv?{!prU zyH}KTdepFL0#eoMeH&)@AU=ysm3s%lo-rnzl~Wx{-Y?av?D!!oT_zKQpQEOne@6}d z&m&jz^PeJR(p8v_XsuD3&by-pJVRgO`431C#sh-x@V)IUh8GR2N@o%Xw0}-*Qi(4a z>!f9KNx9e=k8kz4=^7tbE^t0Yv)dWVxLt)j^F~md{0|nOs0U7+QoPXR@@NqcaOr8$ zy~VB`kuc|ncTq@<9}%?D%`>vlNTEmz{*lEh9%Z?$d4Z+z9s}f#t*OpGGJ&Ph-JDfX z;6U`M`qEVX{QP|Tbh9e)*>qcP^|u=`=*HR)HeMoY5pj$w2bENs1BK{nLP*&$#b`77 zT3cr=mcm|*HP-XTX^y_5$x#ulNMNL$M0DL?mLEA>GDy@jLg3Fl2TmGR{nbrUp;PYq zu{$448T5a1-tL8)@a0FEr@`b2m3=>3_E;^^K;EXkU?pepV~zI)L2!Dv5O|o>ki*DG zb7nUX@BXm$1$c@-n^J~HLZU~4%riOjX6gsHVR^%ZS@hP{B^Np@`CNW_p?`&^vxFBR zax5RoO4?3GVEq*tVSd-Cn&v^?fi|~FKQ6xgaI*aIS_VN(; zC;U|NV^&Cd7e5&8-&9qTDE)1G_3ZPHB)54fLaw`C=#xg5)RC-pKl1xfPAEXKPYck^ zNjTd5Ep((e`(hKbi%w~bQ_?!?Ft=T6_ui;k8<~X(}jmu6CFt42YHqA!_wFRu& z&onr7K?-XSZBU25oh(!&Je~#AbRUxIRT>GbM$F93&EYeENpl4}7OvUj2^RM52(q}hU&-_me6brNS|8DQy&d1N@udb?W-BA7Hzkh{+ z8kg+Q<$gOZxq79kyWFnXFn&dHe*D(;UQ4ph!=)FebZSsUYtG^%C8>PO_yn55Cl20S zo1eKx&?;|JK0vHv8o_gzdei!cpqp>$!|eXG*U!~*lLjS7RAhaWmQX)x2GGuF@a#Gx zEw}(`m~9`gw3ZG{*!@L z{tSx9?94p1%xdhc{aOJCV3-40j`NYeMIVXP)rzUrO*=eL~o5z1*?cp0E{?40bRn%e9ANU$;^B5tJ}B53IbeKN`>5IG-k&?jQ{>t>G#&H8urM| z&m{O~+F<=pa;&7YvVG{`+F-6fyKQ9bWOv(P0LTEmBi51oBWM-eElRCj>jZWI=19IK zI=Hy=sZ0zGNMBW;=O71|v!6%DrfA7g&Mo>h|C+W41Zr|d+@565LxcpQTs3eNG}fn6 z-GFo^%HPQH#eq@!|J75COFGNiV~Ga}*sp&Du{)>PO{Oa4PJv=3)^`@ICj~8lxvUS6 zj%LZ0WVcQ6yx8KQ&0&B~mYRBl(lnO~^Wi>F!sglq1Di;ierw=ZxdkcmW>x@f-jamQ9>mz5WI()KW0`tO=YWn!W zO|WZ6&Mi_RSb87ZeuuS9b?FiV>=SQ-7ru{4Gp_aUV?z)IffFEA{ECOb|J`i>!0YVJ zAHtvJy!fAjw7|q6S0%s5Y?MVgn+9C-%GehRjYr3fO=?8_8b%@11j;ftn?I6KcVFx8 z{-Q=Z0$WxLCeSCHyp!$vZN4kb5|VAP&HVHGRy;;-AhGc%zA~smnB?s}WS9>624SU} z-pdE_C)W#?fx$G)uO69bB$#s2K&#s033Zr*>+IWW+O^@PF`PjWMl zhFV3ZFM`y0UBD8R+=+BX1E*Pv>o*9*qFb?An}VCk?qYOoz3F7c0^k8LetF#@5Ja2X z#+y3(J@A0~guYD@v#)UV4jS=(Az$`TMg;2 z`;Gh*wH7Njc-+gm+`4?^gV#4pX$cNpd2n{2YO90CW&@A?lJ0Ib4+;2GZQ8~XHFP3| z(ygo_>I^{7j%wLKe$}&9M$RvDY-44+fj``&J_7OoJRjLhFc$NOrFt{;M@sj7kjTTGYS}=db(_=^BbHayTLwu`g3P zYQ%P}{lXLur=eJ>!wp?4^h$X+>)Zu+Q&s~VZ(@Wk@2gm9em3VT;p0k*@DqcPzQV@2 zCTZ^Lyu^c$&r}p+i}yHA@9-FSYW1FcUnlD|pc6tviH3qTw9fQ5ovb8xxG9sKZ>I0u zd}CW=vnG`{QP0uY71nh3i3;rCueAS(2RHr@#^9@r5(@@Gplg&Sk&75wC_lK=`a<{5 zC8DljtX*kTkan2wy?1UfBL?y7mnY8*zWYDJsIZ)Qy;jkwdypzCnaKTO`E9J9m@U!# z+2Bgnncic&?MV{rg_h4Zc%GPB7qmzy_qEugrdg3Yw4L8ELSY9hqAu8C(H>fCM!Up$ zGe0|V+CuFBfRCXupG@#yL#^}w?#{*~4%VaXx;pp>47F|d+sqd)X&kWFF|_*I(^YJ;S=XGOy>vLW;{C&qv!vMr>9DZR zLQ@OK&8h3K;>SC$b67u6)!^?Rss?+6O|z2v_FAmZVN{43tcYKJF!SFlviKGIU&JUcMl#{4H5*~njVhXVI~JDk2dB$jYrC^_CJ(iSdrJ=^+v^)nnpg{xUFwZ% zwCS~rD{&F=Bj!!U$qu3gwN*nqmb0}X#OwyTi`S2_med6{@F9p^DA5oAr7%U1@2g!4 zAd6m6LJ*ILSTM~8(gS`rd|G=B7#a=8?gt3@{!3XkdH%B1;J{(V6qma7b=BPO`Ay4Z znrt5@BqO^uA4>CF`yY}F=FYx2O+gVhA9)$DT9EAFTe>y~e?9#0mFWHZaM6;`n9H80 zwThSI`C}4XG06Q%$a;x)J>JCxK|q2`#?k9^VAA$ju8t3!-{O4YygS3F|D8p{_qiF5 z!Qml7GMw#mX8?L9Wrx6jrXG&VOL@Bq6HZ-VEIktd$Rd)URf zaMs0@(Pm+nniV)+Fh#(8SKj;kcnKELmB-iNbw%;;@Q{qBw#Z^ZxkjmUo9Ey#?%TA{ zGY`uzH_l_$CsX&U>w5^0z+)RRSZST4k4JCx$tw^EY$@1gq;qVE+vUY^?!EtlJnp2R z6SQ7cPV!(I-XZ+weYEJVNE*`o`=D-;{~zb0I4qdG6P(jydHq{D2Dy)BH7nekL<}g3 zIRGz6dXP_dH1c=QA!dX;ALi@+qO(kJ4=Mo;6B=k6@uXdyAo640g~#Q{Ke)hRLWY`) z9%gJw5Te4PL5K=~x#FYWe$F*=^0`6Y?QzY)WnD#G?X>zF8s`P}LiFI{e7mn|~jf=?$DcN~o=MN(A+Ajo68(+H)F7530>o7~D~PL>xQM%@WjICW(k<)9>Rs_k#vyNS zT>kPu7L;?&Y~?>Qe)bx?3NnX=manKDf@p($0XB?1bI*&}GHNGjjnGl1*36J}qwV{Ge81v~KMf-!w zQhmWhqY_!Tjr_rom3E6zZwu)!KYB@Nu68Ke? zlIa3W=2KrdWx0B?*E6n2g#TB}M6MFZ&DQA*wTucYuxnkm3DuNaD(|}fTWWR^34#!N zB;+2-)@|woBejhHXVcFpu_?{dm4`}+l!LcxT&p9Lp9wOc8J+GXh5zkUDgD2ERiyse z`w#?0E6QzNL$T!0MQnyV6Us4V-&^{#P`ChEukw?g?zd;M@3HD>@b2BezW@kuq)@*X zRGZg{RIlzP2)j>2=n1ZmC-B)W0F`7%3_A^nF{pK7IjCKaH>t+c&nS>DLBPEyi{bzF z#w?*otE{BxY8UCEfRx+^S#fxBeCSBI-rCv%g+!&@+F$1@AZ>R#+oz4=vD(HnJ8_uh zuNJ<|MkR!B&Yk})GaE$xp3}PrN{q!-M4HKXG3{S;a+c3nzQ(L(+k>v5bSbS6^M0awNWl0tkbo&Jz>juCyTXz@lw9Dx{?i^FWcC13 z#WvD^d!R1V@7cYttkvpV?Emz{j{@J22rJDY{vhyZ71!qLr&uHN*d%(mPOZ~t;Je82 z?6w4XGZfx)oPKri=w`E73RddQ%XbmUvyVK*)XhVVOJMd`8K3%b0$xh&^u90~p?aIZ z3+iL>L+ma*3S_3+rUgC!HGh>gn9h&eBA2p@4WkMqawf76whX%=a37^kK3tt8@OeZa z)?6K;u+AJVxt&S1PuYnoQnn zcSwFmp^tAkvHAPdbm^VBc3DsAM@~Rg6rs?_uh(&WoSMFHNJY>c747?#bwsZ`k1lEK zgtid`5&eIsl2>xE8j0S9oAu}GOi0KW3&KCANx}WT@)Py>@z%ymR_CF?zmq$7z(tQH zk3!|)E!qexV{X-(LfHS^076~acoGGd>_&uL3 z4Hea$`0|4GF4e*!-DO8hYA+Z(q>=fO(>ECz()e9K=AA+mv|u9t40YE~{Q>55`n*)xkkg9Urh1(__v{LC2?(_2>c78S}r@NroTFQTW73rCCuNXB*!+Gg!BH^WJSfvj#APi?_Xf8fb|Nyu~izfs{%Q=8W2-! zFeHB#lH~jK0WMthgqyK0P2nnoaX*1U(a3G2-cM>Y>-`BJD|k87VAz{NYC>J_S3@*M z^bWs5R);c}o{X3+*bssv>;6vx8iYas(Y#JLrTsQ56i!ZrsP7d8F|(YLWWxfmcSt%7 z2;kdP=9=qbgE#?mM=AcRCc41&+s{D%D#sfZ;g8c8(S`3{=R{`jX~0L>TnF3$`HAlr zM*cdeTsDGU0ZPS&0|Y0pd~Bk=h#mR_t$3ro^gSd|DEVk%x6zLWR@;V;1Y~R8YX6i2 zrHcT(1)1b+McU>Puabx??%M%Rw3^8eQW{z-Y8YoYKLUMBO@e*;2%n*TO{eJ?P8N6wEAK;Cx;?&AkSw>(Um z)AwZ!dr0tO9C(H0%}377+0S;!HQc7o-A6)c)^exE82q>C-XP6wdiuC~D<66ez}($~ z15U4CN4p~cXbT9!9SLq>`jTHo}n*60rK*ggE$ej*gok+i8(XP#Ev*=IxENUQe_(@ln>X}?p zaJj`K6h!-oP~#n2-^VrzPvxVvI6^7zzIb}6ESY4o>Z zF2{EDB_f^OO&w-6QThNde{BH%dz^N&za-rfN=}MRDGUSkB$T{wW(AYvxLw zbyi63q_OFWiVx+M=m+J!_l0Y@N0ubhM57Didv#-LvOltrgL z7)itf$1mfixdL` zIcb*l#o=1oCbL=*6|nL8BNIy3Q11R-Bv$M^dAh19C{Ga$v% zfZX8pa8OPGq{)B!l68J422%)W2#M+?KG)=qqTm3!F#P8l_+;MM6d=KCa-4Pd1Bn?! zgzQh5#_0+x9dMeX13tAKkTih4*q6sh7Ielv+8Dj%L&pGb{}Z=SW`6EHXbGWkQ1)^7 zA(%>)<4+V5qSkK5o8$6*t-&OC6_%h=0zSi#;H7~+S3Ko?pnBSHNMD=z@V0k(58YH8 zr{l^rC1N}EeEqnPyZM@2vcf&F&0^RB-WS5NR>Cnck~i1@hUeqg#*psq2kI_2vEDFn z7$mg!9wve6tx&7R7x;IXrszG4d*XaZIE|>JzcV8p#tUsBK>(+rN0Ejka$9Hs4cJSu zMCY;a1t-8wNZs?3S<(FyXRtM1A`v317tf-_KUL>S1a!Zc$Ae(<5LpT|d72e(#S$4D z7=E3}bl8OgTlrkw$&8|iK{C)uQd3dA6#FGA+%8K6h13E10AnS9o`ZrQ0KD1wh^pKt za-Qsor_V?}+1Ts(`#Vs$1xELVNb`$$g`Ff+I+5D>6OjhK6!zCP_B;l6#Uul$w?R+Zci!Xq0K{w3CRncIv0X@!S31H4GDDIU+Vo$rU6o6 z5$svr669|JL5Rm>0bKlqh{lX#KovkmuloMf1CT6(8_6D?{`n^NUjM~G#Au-ocE)Qq zi_hp+$d)@+^=INgMCDiKcEO8q4@<`;wWUlqa~m)BWn)K1#a@|1V&&%91RVB|G4o=;gv+{=|86 z*2UV;;)Q}5>91Y<;my|rHuR~83?%=tg>epr+an1H_UkoVkX`}kT@QX+#e)TvL@ww( zp>G!xG;rX~&xbdFn)~h`6FspOB1yzE6tGB)pS!#r5~58B@xPnnBS8787@_r0FT>~( zJn{NCI2RaSbsvU+Y%vFeOOcT{0>q0-sX^TrA%xF0vT}&rlCr75DXK`o4w@6B4sg($ zkUU;4$s22YzaAbEvHIHQVfGoxk7Xa0($9Q|V1C6paL=(ukL_wdwKCsVg^z*y1tG8b z{@4O#maXD9btD9oVz2YojOnhgXKBV zyq%}0Nz?kvZS3)zL8h*FH{P8$Y|D{4IZeo15BstBi!gAr8(@}TlR<7ReQ)0WkJk)3 zfr0loKG+c#d>FM3u3F-(vVuY5s(y7J7;4;8#4!&+-%*no&ojb9|iK3obS9I8~m_B(J@h05lPrn!%-W8X4W09@VuABzB3s^Vv9?mzh38!+Cv6>~i~ zFceBvfF1OcVk2aeg@xXIGaJtN!NN7KR~>${>!mZ6JbrMave|xVXk`ZA8&23^Rgh{p zyVghhn4v)+gfyTy<`tRhoovrE_K>PZ2pbSSmE6^N>|)R{HaZE}+g~{oI9=&< zSGv*}kwhP@YKT#$JKr2e=XKwskRp-^tF+#nH2CUwy!X5~lWbm3i4zdrKM6=SwyZ(X zeD!&lBF3+2a@*XZJBD3Ko@3&7TTdYf3hRUdDhj7S;8rfRTSUCA@r_YN$=_h%R|zhB8EI9rBHnKxBl!p(FBqo330V_1pqdyGhl zB>=y`hN>s!qv-s`E5ES*dS{`-4KnNDXb$_yxy_Db&Lt>C%a~JA@vjOVWg5*%SHwCDRhCA~uX8&y#{HJ*@jv zXC=)iU5TA%JAC&*gYbemQPjsDd|Z;t^&EzhLv(= zU5&PrFBqP;Kw{Wza2DDgyI{BM9f+Puz35N9Sm}siuz5v-=RW6XfB(S>#x(J{_rM#ELV(+ zh(~|kW6GV_>t;zdsPm=^H$R4u;>m?Txu4&0_uO;n#A1#u;K#+ahF<;b#{UddoWqoA zZ$5|EyQ?=byPqHC1ZyZk;da1g>I{rf0(j01+u+L3#Ip_=LKH4~~ zm6kRiucGvB>;6?G#KeB%7d2LOL*ItEnFDhvWTjhJxE_wF+Reo9q$u`qI_y9b0_3iC zI@F_AYhejceKGtubcQgm1`+=9JU=c|&bh9ioMakavM@Ti2;3c_J|73I3%GM`@5f+G zp29S}qjy=8MSK(XTPyvQy~1R%PV-`i?br1_!vcK^o%!t_PdC@TrEK`2r6ovZ`m+O7 zI2whJ?V}PE3RSZZJb`D7M15c0p+UoB9$_aM>dFHyI(6?LYn=>V8owrwvU|W7xQ11s zvEX0_izT92ZI>PRw#3L9tdjj_5@#&u-B2Qz4?S@NAdsstPzVyYKWWap{N?R>c?M)d z*c5*Z>e)9i4~%L+kD)9nT=QVdk_i}4RYpF~i)?K60NJXFG9!iuXx|he;_2~%P&#)Q zKuDIpe%%2^tr*`u(^ATngNq)+NS&Mm(s-7~E&K&naqrpH|B1vXU7Xl?E^xe92R$2Z zZ0wmlN!2*$!};W3%nO;WJVswdY}1rkKC}{+L+O&_CZ*{f=P-T=l!PmD*38K~Dpww- zEmgdZdyGb*+hK6!xWx<8=Ai>~l9}u;kSl(;=`^DhOi_L`Pw9zquQsgS=JBU3aJ8l^ zu2RHOzRhDchkj$mz&eXQYUTtk{I$W1rfklYa2hjl%xf2wuOc@qmxcsCjJgtO9xb$E z2fh~{2H2FJ{7?grXl*}yxZ%=kkLJF9bHTS=&;5I%=k{$G_DtctZ#e8Wh3}ND^C6 z#iUK26qZn*-EvSS@albendRe0)Moe!Cc>Gvp6rS+Jih`wkLFy}%fgiJRNCgXI=pyN zMBR59#!{^U2`DDsR7z3+;{FM7SWa)F=C+gBG=RyK(_@GXcSrcji=c5l9rkMjXjZj* zzKlnNQU1#zF8Im#MP%RnW}RYv^OXy=wWjqY8ZST?&UI<5#f>9ib0R^vnp)g)!*7#$ zq1R)ejrAJRYr-e?JZ<4#{6f4baj=Ku=9q%kP~&+^?LD8Hug_};38rbl*K=6sJ?c3U zbUCE26tG@IM>9?G_Uer$Q?&^5*RHb`sE^~q_DtgQ6XYw_y+Mf30J8!%;oH~~RF6q_ z9CD2ziK_E0{9pKWB0VJJQZSur7gR;x6P1Q!-WAtPflF{H!PaLkG{(l8Wb#JJ{q?eS z9}UXL2ZRXE>*F-sHnWONSQ&7=I}hB{!#z$<9~gm4PM#1*r#eT!I<-H*!tcF#R$XfD z?_0(=KXc^=xvqVGReowQ`pU4Y(f(0{$POt2R}^MfiX(RBMY6EeRMim0)*B~8bRR1@ z<@#bKagz9O_-TTG>yxdx(Y9_Mrtk)N_MvPg%&J*8(#P>-Z3)>1KaBv0J>~vzu+7uw z^Z{eXNge*81!6-#iFMBcHAgVk*o5&7>u*d+f>KDzl z(%;U(``E+HAj^!~7UaF}!|97V*wk#24Ov2k!ke2H*@yY)Rh%V5^}|QS4!+lbMha*_ zt3XBNqcJ^c)er)}(d;fZI4%M-Twtv3F^;vBrIvct!-X^RRyAD`VxM1<|CWtrwD#jU z=+U+AvZ__{1&UwlS8?~eHW~E~D3JSrd6omgKX<%#~KNRerDscv(~Cfg9-9l)0B1EU4`Zgae`F4qSfA36goO6q-EyDH|kzK9KT;tvDauSERY zI)!pchfM)zJP+%|h0Y(3=oNY6aS>_0$FGhPoOjiesoU8{L(YSb=L+bBSM}R6wq4JM(rz3AzY-kUl}@_ zWnYMKwXcLYg>t)EF{j5E;U|ph9ju$1CVd8^(X(pFLmkg#2}Dkh^;L&UOUOp%JC>Ms zG6jB#g3Z{y>C*YiPiIdUxi-Bhje~zpS}kLuo7+L-vY(vIT75kqo{_j=N%neOB~!;8 zb8+G$@P&Hkx@Jw zfm|hIQ-pFu5TQ`Qb7#kZRaDnrF>kxX%@emBl313P2H*1~7) z3X!>Ll8!8;z~Pt5HCE=hi#M(3YyPsW}uuD)_Bu@lWgQ!t?vu0&V5I1#DD zG!%AU)BY6p3&&bjym^eC-r~k$rN51m({O;z=*G-@p!ZUl80X!ykg)X~!{(`BIslK> z#ri?vH;YN_N-Me#c;a!&W93pit0VXQtx`AjkJ+-O5Bj-mOnK{~} zmeU#mQvfWvB)Y10*Hqrs<(B}$zk2*^AVie7xxN}E80!u*T7LrsrOM~`Nu}x7TNjT; zbsVew%k%y2dN%t$X3U4h8B@(!LS&WJE4D*K+vTV|YAdr8esX~es=|CVtiVd59jZvXk?Nt;%?s#9K9$?vx zZi1kaKK=@!LrG8g^!*Cy^kee5@ zN>P70ROFLx9~S23G{uG7%scqh2#CKY@4H^MH;CEYe=|9{>Zwy7MlgA!K)V@fg7vWW zeucjCV9Hp$DLfHwK3=>YuS&kv_|4eq^pr$fdeyJx!KEGM1Bp%7KR09to>w&Vto$E@ z(Y?5SKZ(a`4ZR1 z`Ff_rSdKRREFqT$(RTely&@JPh8kWqBduCMqdw3g8ABxu5L~Pb=P|5(pO(e#I&`P& z1+;f{*RvH|y>qRdWZezRhA)AnO*|m(IlF<9$e*4lp{98gY-~0TpQq_s*c8G|vnwpr zs-eu1I14GdA4D97K#zsn7o(*0QT`etm8AGXSHN-dk;F?ck(?+7ud3Obz;1Qhln;&F zryr-xBbhZJvz`KYsIFzIYhZNuHmGp5}TUEYpmuXF0_#k3h6?^7+XtHK5Y-B3V*=B z4sn)(+1-P>0Mz!gY~0sAW3K!5hjr=&p#-#WGvnR_1?S&+U-Y`9jgmoo)-0t^0CDG_ zy6NTGekJ3{u?qz_)%;?ZNE>Lu69Iri<&ZRB29-*&ZT=8y3$(G}>;~chKYkNnA)XaG zN~QwiOpfF0?G{_s6DZRl^z=xl2GT*-}_QKt2~XYOE7@Q#~V zE5{0mF9J#}c?>F8I*SewVu12Xxp+M#!EuO|8B8Gko^$esQEy_8_%sasMoQs?L@adwVv7tJ>{oUyL?|#NFZK zc>*GUC~)nKG&U24)32SbksWc8kP)EY^sb}n8#9|N&NnVP>Zg5ScU8={H#510!*qAg zJYLgj)t{(Igp?e6i+o!9WKtWU zXdPqh-moZiI@?&#%A0YZK9yaLud}(ssHDB2joDt#3K*v5DR>3V z2qB21C02=iz<2?ckX5tp!A@-=x;jUOEe4@xStuQiG5i>Ye5Wls1iLIz`bm0cJd$fTNVSv;s{8qJ{uf4i@`LfMcX!m zEWgc{ZRe?4T5&SM{bXaj84f&Qo%p}|ixp(;EJ^HM^{-~n>JLoOI-PIw#d)edZg#0q z{jtt}NE&bw_@{ldwQFxwgs4A794(mqki^$b=uujRM-W%`yDVvC5A6~HpP5b{pRSR) z!M3s?S%312uy;Jz&!qRC+_yLL30qfIwiSB{cYZaH!p>Q=npq|p!TjLd{+hUqDO$NN zI%oQ!(4_m4o2t@#prg^AArFVDLoWxAwOzEOL~k{w6dsL#@rLGgji}cE$iD zoqt>UqK_7;!I?rx%2F+x0jw1{6wZJG*~}p}fWbT~+!Ct^J`GnaA~Bnxvr;0U14db4 z(N?(Yu*9<%`N^`soONA=!B3k!F6~`fsFa{5=lrALOtI0%v0}UGYWg2G-+E0B6v(-< z6-gdX9-*3vRam|w&5s{x16S71A5UMb7vqn37a-uIDy%VH`ab(&^l;}ADB4LntLs9* zjiTFF2KESZT-JaXeYNd}-zh8~&ax~C?D5h{K!<{o4zwcxePfFJzsKf?9Ghj!iyk_t z23|NJ`Lk+S-wKoBXMA0p#l086$dQIWC=Rppxxc0SwbCrN?P30pTyARVwo)mz2A$$8 z+#Yjj5B0DJ#rnp^qo7Ftg7@3gbHW6q4ljf54c)KL227$tQ zq9__5*WU8T7s)Pw2!a3`8A(i}xi*meL`(yK(XR$F$^}qh*_Rr2#ID@20K3))IP6C> zzz&K7qs%L9m{Ql2zklzUwuKDE$fKyvOICc1%d!H&p&V^X>_c2|@DF<{taYhcQJL*MadI=N2{bPWi7me)am}0G@@dR2G(gmq z9?`=U8pH10sfi}&?t4DmY0x{0+N?!t*)j~CHia(2#9$TWANHXVun)(zv%zC)1xScm zOR`3n0)k+^x>)55NAYezUs+4^Wsdo+L_ zqosahFu{!hka0Rb)4UyZAWx;!Pb-d1DI^ZqUEGH6;IKjwo@^G8@Qs!%r7`jGRJmn> z{(-2k^#PWA4zOgJ)!3=%*8!uEoOg-#DfwS)_MP4oTvjo)hjt%_+qMM}^?k5fO`e&N z%}_5fQY+GZ#fxgLAICR%X+;BdS#C-$a@$g&4F$FnpISqamYLz%xzQehNRw;JbvDp% z;N=pGvo1~f+k`^kDu6^&+z(t%i^S2Q4$OmKwh&nXtY4(#9Pp3 z=sK@JPr30oKF4h``tPFUKq)l`*iDJ9@6UnUT;AsqHw_=cA#QUx40vlko}5oDY>w-6 z-)jZ`DIkQWd+Yh_f9e(o|7lZDK&Ha@+XMB5&}^Zr^CM9pBbZ+yx_$?NARN3XT4|6Q zg|05&$4dyPhzT{Pg*kuj`Bv4nHh{O*dz>CR;hkvgw}!Cbpk~!H9W5Yl3ndQ%oh&5y zi~UUmUJ^mbgJ0SKDO|=OHz~@kUo&<~L@s$&^AhYd!I*#<7PzzS7T~%4@#sPowK*nc zv){aM2tb@JXHS@)0ngkg&|Yo&O97 z#tGvZM0fh!4y3FEHawP7FXOmO*<21y>_82EWeyzH^uV4B`g3@XYP&vv{S}nv`S)zV zjla;NU!ZM%KTu1O2{?2!u##-;45dF25Ucnt2zr78>b%qyOqPQv!MyiB^YPN|B4~UB z*l9ukh{LnG-^lq89XIjy&u~ft{b2xi2A99suGxun0-{}!kv#P@kG9e;z~~Rb?~Euz zLB0QLc9s$tHz5%6f8^@d{ossmmUGd3gaUG-?P2w4;pvT|vc1~>{Btv3e__yt0Z4QG zY8-cR=sB5Q)*g*$0+%lvXlGG?RXSX#LkScy?fwv&$RY|po2S=jE0mFp$`3&sg?3=f zR~8v@-X6>hlac^J*fQM3;DV6?EzKi7w^KHavX4HX(TE;s66SPuG&o##T!1EqWo0^nT@;BXu-=l)w5<+=LLgnDgXiJh$HStf5EoliK; zEFdFuWA_VD7+wKjK^T9k6};#B(3?P_S#FMEMu1Juuk^!OKC(ASh%|~(`Q6=k{c6y& zXYOc_xqYO@(dwuVh>7J-T7GsD5jV9zBJ-*3B%;g6{Ot zxgPPwJ9o$>-oRcdiBrkx#`Y6mrTIrJlif86Fj*E;BvZtEN1rU@sv-t#NS+1IYS2AJ zG2-J4%yI4)3auo`*^mAYf#_)s)PsB=HSl%6I7as5f9MY?KkuV3Fj-+pgXYx7&@%T6 z2il?=BqQ&|H+TaC+>%j@QJpIp7{-UO@VJ`{e^7Xb;rQbG3*UR^uPwnwf>yGq+ap`c6`< zjq+O+5R1s^I`7P!&P=2x=y}%yMB;DfBq-hg*b&?_egj+sNd0pxEj*T}?&B~cC{odY z$yG`Jue;I1P~yZTbQ+5FMPtqkE5KT!0)Ys6Ve;Ep4ntl@Pbo&mN45d7Vr$F{_e;>} zWxd@Gi~Kdvm3{(%qbRd=N#79Oh=rr4ppK!^WQXc!8cr+PC>Hv+g?yc8; z=Y!9Mis9|AC(fM$#{2hgICz1QU%v(H31cc-sk5>Y0VJ<$5|12PPtKEIHbs06jvjh0 zF}edU1{?-|&zmd9sF5OrcC09x9t;*mZh93_ad^Y^xfvTrx0^9{hQ#|C2ifUzqGEoD z573F&YZ)=;lWE5&@?b$um$#EZE}wCI1J+gw-wz)lDE}K9HJG==Vyp-yuTRERJvmmv zLA-FBLf9=!7*-@miS~jij*U^|)7;A=$F^c##EXp3Pd&#N+pBGV&1ydS3_4&eBs$J0 z2$uZQ83Om31h|YoQJ~1pCDY^vDFD>q7mHSP3UDHX9&%phfwAF$K2D}Dbc$q3bd_RE zA?7lMbFXSZ^PLm& z({WmOuaSZIH9ogBpJ?mg6cZM~XWO?3f=N7uGaQ2cJ~^8ol$=7W(lK(e&}iOv@v=Th=NC}FR>X6JTE@jZ(E ztLMf4HnN}KczGEJ^&Ooa2Su~!qzt5Im2;4pp4lQ~X+5U=mz&8$@#}baB+=*HmsHr4 z9K+rVac503j;rG(nK}K9{wy?zKl6Yw$iK&u>oi6K=W9s2BB{%m>xp4c!)?i9d_6Do znN5pSWMr4*k$pRmH&mFi$n4B{T1{0#kS=@x zk`48d_yiYNyLnXppo+d9rAmpgUrzFW+;FzYLn;%59Fos*@NQq748iq-o2f3|c4Gs6 zdhY<6qJHa5W<;|L5X#&E8?B;Kz{ur3_J{%oIOFA%%TqeiO$=#BfZhIw<-BbM-$XJr z*_6H<`PP@;gqnCNMl6q$dvb3wij z9khtQkLhi0j*+?eStciPr9@u-;bTx;h@Z%r#j7zlC)W$jEk24CTFTRqVCDGT9g#ka zo2kBcNa65Ro~^mK%A~$V7HB5wd)|o;M!mSn@-BEx}abIHVssNCX6$lv$;*_W!LONXW$+0&IeWH-L^2LACIX!{u6sWG;w%~I!&0ad{0 zjZOl2xGLne;|q_gKE5A(es>N6)FI8$lk1Bs>}Kt6+@_0|Ezd>TL)!a3txssBzlpyAd6{nDoDIv4f zVrQGEPc1nIP|Ou1w9y(I&^8^Cdpv6F;57SE;)9Q1ChxeRD{$WbqdQ_4se?1XlM_4jK3ml}etwOy_$e+JOTvt?}E+CI(9B7t$xcyNu zC5l#>kRU2znfNYqrueJ*fQ8PVQNA8=&gr99ItxRIcM@t2Fn;5<@^B=qyKc?UFi*OZ z2{GaSy5P$v*fVU2S1=igIW7gNBmBDBNZ%;U)8EsC0Un@TmNEg+ax5oNQV7CCJkQxb zXttDXCn01BLSpf3C7#!n? z-6Z(SxE4uDk!OFkoD7=Penyy=<&jh!r4zn`DdMkmMPt`${Y5zxJJX07*ZpV)Pde^U zTLqrd$I)h8mk~VKFi~_XZVJdO4Tr{YBXf#%4JVax-Imx2xqZgN@P+7M=@{GIN6t=o z>05UxELFgHryOA-UZ{TE`Mv(t=iVGv!A;X8aRKKpx-N1T4Lopqb^pmjT3DXlH1+lz zxaB3Zu9Ia1ns~hEi{FYFG^ru)m3pZ@O!!@6amxiHIb}Hk8e1;=mjo^aQ(;nQHm2k} zIgM=v6QLxJrKlV~u5@m#aYt6bI9_*QSOIqetBkfVB3G4FRc`6Uq9Tlqv0eIg zZQY*t$Tg|lr=z_`6|DA4^?1bc^Ups>UB^wXgqpneFl)BGS6&#-tfz!84tok$=S<)c z*hi&OeB#s*O0)#z(3C_h@9*T^`-zKAD)Rndm)W@&gGKs*0!+ktA2v<+Taya!sbtDK z(HJ6&r45AoZy(PRAaO3Po`jak-9ByY-gjIasFLpaCP-oP>~S?_+ryADS7!ykObk<3HUq}{tR=c% zzw1Q!AnPwhk)W&=N>3sjoD@b6wJL>|2N}|uYr;&EPZBMf8g6iKuf^I4uRzz$2RDZ$ zou~dl;>%>e%Wv#BLS9?1_!r3Chp3t5>Kc0$8n|OC9#nDskocTuO1|~v z@^Z^ebqJlSJiRdUHJL~|Hs<%=;TQo|UvebWQrXv~uy(7hCr96?6iJ(7gxpb-A+}#R z+D{_;jJ2UUpKQ#gb-F_0v9H2Z7vU+`*Mtw#F2*g6btqzEb|%(aeBeRxyV zBBQGJ4h!2^bqC5t5C!k7GqZP3=iRy7=}5Kf+_Kw<%gkwP2r#NUnj?;{j+;#m8WQLe z2l>}H|J-F|WYnrIl^7y*xMyYM^j(>^+-kPqqq?g;mYtn2&b63dcoi6aY*0gC-*(95 zVxxyjkwMjPQ4a?+&X;{Bq9Xd|_dGK0drtnJKpji3QJN)}{%NeEYWWX=U;qKO^>sew zW_L!Z)6^&CSV6|h+!E;d`IW?&-RaZ%o61^Fqsmh3gFuqCKeC=Oe)~Rx&e3;2>VDEr zX%hV=D5u|b#?6)>VMlPS-Y(lDGJezjA&uuCEZUP+CPtoIH!Mqx5q@URZhNNopeZq= zEUn>ene+uMtFrEC!cA{DwYNYIn;{EDY3Y^dI}X+up6Va68*WnG43F5^7)EQC251Cb zC?b95O=?^Z`0L}@?vi@G_ljn{76@O>^IyKK4gR5wFsF}bcJY`S9>pKvH0qWY)LVbq z_yuj)bMo36U({LnM@1YX){qe_c< zo*5@mWeVLglu42Lcj)|2I~_@ar>bgl?aHvQto1gSjv!w?vz9;zTK^2sD_ zBbp_}ek}|8#}fhs-(PL5@xK@OK12&LgB}f_hdCAak>q!$tB}L1TPZY4qZB%E@STOw zmGN#Dc5-XrH&umP6K%impH|M5F-_0(vV?gG-?yY)oP6;#Qi6#%9byoaJd?;7eI2c5 z+ad3)2AZsbmc1{*59W}UAeuJrrvr~b@W@*~7#I2wixjh1V|tkqo;(vZ^~G)F?HXFKT@ouo_;%R@a%%cr*To>ZXH@sOXC&~CI;=jLsDC%jAvh`Onp^e zRaz2i2_zWYZL$wq&Fs@jIf2`s8cP~9m;b)=pX~yE%>A#nt~?&f^^2Rqjj@d_`!ck- zrI8|3h$;J4_hv1-L?UG0D$Q?@Eut=>v1KPienVv$Mz-6OB_uRi6O$`L#P3Y^bG!ZV zo4?-AGw=JH^Pcyd_j%s4e2+E8Q%%7y|AJQ9gy!Bpmw2TT%*Bb-u<)1pt+KECzYZnFVzU1pCP4_o7KwZ7aI zhvv1>RAF_(LTj>kGp8$R_eT8!`(uGlZKu@8Ja|utA99Jk!`|b2fwjMqryidHj3rOe zUgsSFC4``oDbelRCG##-`Rkv;BkOTn283PJcV{+Ew#T;C1iyIn8>IdHge z@{XsSTcgSBjE(jU!qmmhFrP66ty4`lA=vW@SUvj;g?|<7G#c>QmFYp{tufitfGwa=%hO%_cu4zLb?r_Ra_g?)A z62i!nJ8Beok)v3h)|_Ij8FjbqTbq6NFYt@}vB-6Z_1^d{rfP9GRe2hHXfN0GDs}0T zH-_%WdzZQuoqWH&py|Im=@xRXr?!RE-c9+zzdU+3Tysl4<5b=PsIgr|EIFGx_GvgF zb5v4j+p7BN5xcp{fK6VJZ(C=l~RpV2Om#rQ^b|9sjjPOniW z;=biSOfmksVwf^hg{+}>DIO0gqRZ-Uq^tna`VQMPMI)rnhF0gHX6#23_@(E3BaQVzoIq4027D~gK`7w`Fj)1x+v(w@3?5{ud9 z)2s#wat69MQnGOK*^KD%ZKY)aNBndl&-Q$xjUAId+TGlh1cO+~UD|B^T$J_C}4XU-;kkrFTr$RK1HN zIFzKxJI1eR1k(?qE~*FhHnja>xZ`AVE6}U24xk)?X{vcykCKi$M6u$KJrS9-=dYu5 z+Uv~Dd#XzFBHd;9kk8Aaur|j!X4}j^ccsRcL`BW@v6qiT3yJxT>z4`n5(DP)W?0=D zbUlGP9>wnpLXZW`qq**~u#rZbE@C=1#I@SKR+w;~*dF~a^Nr-68vGOEB)g&CE?v6U zAVsS?)$dO7Nc%6v)7aCt?nbGJonT=+pEtMb?yQZ%Up;o6C4M5-S`ElQ3NqQBXhLYz zeALJ}x4hxwO&%#KUZMrOOIz9y=nH?)y%E|cH-0>7>84|)EyF!XyQ?ck{hjREX4(V4 zfNLjdb>ocLxurG6Sa8TP{$`a@@kPh$^Rctx8R1-ESn+&CgUMR=+`Bru9ZU(s?JL+b z%*&@H=k#vNd<7JPjWX#nUakloG`%>{AeqU|cOvk2Z{l9ldoch7=mN0FP%>GV6be3B zUPu6koE!=iNS6O$U~0+>h2F6+&`hPy=!|wysVtDgDQ1?MHy)Y-ch2~XkZQb4*O#Gg z$`5*?RB3FI*qdi~ywit2h>Ve<`volNtzvw1!u7@@uInDsGmNpyL?Z1!)@v|L?Qm%m9 z{08#ky)h#$HBNw&tpP!a`N4_=XhY-#j%vT)U@ADN1*N1CpgXXFiVFJ5l`By1nu(u< zwn$Fk>?XfHf9@Rq1p!OC?9T`=jOp#}ZUfJX-(S;aA|fL42M_Xt=d_i0DuIRCIA#X8(HImD z&$S0aMCQWqO(=lHXlRJb%F1^3^iZIbS8eSaKTXwxg=;=PupgpSHo);z^=iH}@C>Bx? zBJxy;P0bT9O6Wu)=qO^AEl8TLqmU>Uc^)0;QGs~1rTHGTY|*=wmo!e+Hm~T z`*~zCURM2jtvYV}`QHew)y{2!%n%5{+NrX-8Ba+;n{R-A!S^X2Kkm?dpkV6_1n28W1eXLQ(3ey)Yj*I8$3QyVYy+#P81#npwBM-P zBmqLHZ4fVzx#TZi(hv1U)G%(!yX)>XTP?Pkwz> zX!2Fac?zve?*nuah!niOlLEQD_HFG;XJU}*XeUBFLZK0ia^Hk0vK~bfI;gKBiSYHs z78DiFYtnp2;ub$j#bVDq)7?(isg5U+F?PSCE+;~_MLwGUhwSX<(mQt+wb&d~noQYP zR&cVivI_lF+po`@AK(E*@u4MS8PbBhiFn4>OWbYCOo(hW9m1Ks!1vH$)2daJ9^5Gy za^~W<;JMT7Ii8^ye*nH{@SD6*pE~A$K_pMN7o~z5DnDwF&*G1P9N?y{Mm;LU&zAO` z4Z4m6Yym6+_Vvqhy#*_D_&f-U$8*edWlG=NTO4LM7SR4Usr0roc8@Vz<`^UTW23*^ z@)=jCXkQUO@qZ@grSU(96-T81EMKtpAPSqmwX=C>NBPY)V<$e>H;3>rL%Au>)Ei#S-@D-s`ULIBbLpq zS@xXQFwgpFEDFX}YiBzDxen&v18l3$wO$?hX>3&(o;)^_*_}55~O6m;e9( literal 0 HcmV?d00001 diff --git a/docs/assets/images/subnet-tags.png b/docs/assets/images/subnet-tags.png new file mode 100755 index 0000000000000000000000000000000000000000..dfdf335ccd7f07c05e9dc2d71f90b7f96d43669f GIT binary patch literal 38974 zcmcG#Wl$W?7dARb&?H!JCj@s79)bi9?(Xg`iw1%Q4<6jz9fCuE;O_3Sxa{7|?|(nt zx}V;vx3+3_rf25#^yxEwx}WEn?_U+9-k=eo0RZqu`irru5Apr3I1OR-;j8-K< z*a;+KSt)S<`tSFvqbLDZf@xx;;0^%D0WiaSu;WEol@3PoR>d$YfVB80RnMi9RgkXA zeh1$LM#V?FVJ-HeDe+dsb8MYh9qIF=a^^+tVzhqq-o3Z-j8hD@@C{pPiwrA_)u@$0 z(+iBvsEsNblVb~GGi5bsr>|FEzr<80vr%SJt6?YMkkZy?)MuQNOJjyyl<~~of+5>p zR?g!tSzxa$mvP#Cd@R8U1ThrKkgo)*-zY`@?ff)?1Y(Mze#fEx{dM+@?G&FM<-SPyGTvCW2*_VD>C}cRqxr4LVk99t{vTKo4QCF*)rixPTs%$b*0vTNEZV4#R&^BXzY zyGI1Q_P6+ZUedI9Vqb*;?6mlJSbqq7fZ3BF^6M>)H1P0Li2%8eo3YQFv1^^OUA&c{F8$WiL)tB1xN!kFK8W#r8(6(o%AF~#0L9O;2JZMn9TNXZ~1k!*UEKg_ZB<#iYS19x_Mr%MG0f&gB#DP>=X*bjW%I8EKKT6Xi9IjznWVl zz9>cfNI&Af)1vkXQ!yRjxV$P1VAA5-j^x1s3)^_I>5-U9?}lrl2JIZ!59eDA@9?6j z1p~iU3VTw;A_O&;w8`puUn6=*nAsn$d1w(p}%wv$yx9g}D-2aJ7-OBC!dZ?+-hRHm^@Bu(*ASK75mfLL4boytTP4wO z%9dS2`OTQz9<}pkH*X&i#jrlaG2r9BqkeCWe z0)DTz9|fjT-ZS>wnEb#>QId(W&8Nw0Igx=PCZw^soLR0XxM~YK!X6t1TDwMn|{UiG0DNv2Nry zFV7n-5}OL`CP?)v?GGA!HN0Z_aU}y4pI?(l4mr97W8-gTc8j&L+`3VJ_dUbMwal5i z#it$ldCg~kahzeED0K^>sM)cM^VUSJWoQj z+7nbEomrA&BD&vdYkTd413lH-;}Hk!ns~WCY6UoDDVfRPnjuPKg-jexyouh2HV zjer@ki;a!wJbBTJF<3(a8-+=bMMXEdgmvA#>aOZ$u_?r-w2U>g*ZAuu*>Rd7gtvuiX zlta%J5w5|}ISpPfIMFXojY9o+1Q}>G$q^Z13B&-RSWP1QfKfxUs4OTe#(WI7Oh)cZ zG^u=g(YRFK!Y%P!w}NW%F=A_phCF=7Nrt_rHM0>fa`w&q6-Jd-S0|k42Kd2ueBh{- z$a~$|JJG#%9FO?((5_4x;()!KjZHDL`|t70)|$7xJ-v7VqSQ%0%FD)#U4kW%-u5o3 z&DseAfnOM2rA)7RHm_LU*{^f_#)?ucHT`RPx5(`Nb=p003>naGn}uUYtr$K-0JJ4= z@&>6jQ+vPWAd88A|CW`rsi`yO4Z6Biwc54D#kI`AN8Hl7te=3@U94~6qI#xVL0uJE zQ`(12#ZI4bfeJUStf#xW0hhzYqA%lUU)0fW?9?0nfNW8w)pQ%MiY#WO+rDDsV8wo@ zv8cD)WWg9d*-F#L_N$6~l>$@ceL0XbV~U~st{{% zkgiMz05MKA+g+d@sSio#Okd*ydlLtB=evu!5r!lAyr#$DKM?YH88+2d^AlPvt1KT7 z-oNFukr?1lC~~UGc~9?i!)QDOf`+vk?*Doc;TzAE$3%n^rAwI29YBh0%CT+HQ*csf zBL;x>D4*w49LG8S&*>PV#d9B!V}1ul_}IQlbK{x?f)&7 zfKUBBQ~>#<+U!K0nK=*?xm7C@`RwHS^DP%FGM-g;$7f~YOIY>w{Z9vQ!fNJrkN_pI z&D$wzRG>QM?HM?;*PY-lZ3Uq4^Bx@+Of#%lcAo1vbWgwi>B_)-+~v+Ct5GY>NC^O% z_?)i(UgkG=nZI|>89mZx;p&-O1wN#W@VZj>)V%I>&S>yfGs~M_`+M+rSW;wd;mDd; z2xhjl-MJwG9w_XE12VkMvv|k@*!)+|$Efbyw!|HSM6(H7sW&bz8vte zFRY&Nq@#z-@nE1J!e>t}4FH<9`oNFUtzvd#>^~j8`K^u?O3H>CKZAR>yB~!L8*PTe zxv<+I$Xr+n|{LGXnPg;&wGsX-vo#7G#n<>G2g#gnXIu7Lk9APU!`9ih~l?M zuEGC&BnnY z-o4Kk?qL)GfI!aKqo5HnqnkC!vT3XR{EwbRwjbl*Nv4e|nXA|uPUxp)oA68M$L(FuE+RGo2| z1y64InRrtE9sx@6u*p)RrtRDDJy`sbFcUM<^fchpS|@xns~DHW0m8A-;0KifSQu;w z{&<=Rw844InEUiu|Cg^ezML?UUR`kDF>Kl_+Kqyclva?4wv;j6Tb9LvCV^d&p>Bg` z^MTDVX@K?LbVD_A6&dJkJSqT}A#?ZJyL^f_POOZJ=6;QYzUmLlXG+SG8`r27%q+|| z*_$YfbtpMiRZ3tCjuJ~+E3ThRJVn!|)lFOrI)8ZV?-+Y;rF+Q5a6Y}x2q81_V2tr$ z_#}MbBE~`vx)mLYS9g%nCbdj!@l-+p!t-mLvRe*|1^#X!VD_=j=?k1iO1ule4~QS7 z2Pk%&jM-Xx_Aje}Jazf65%~o~!6mI@ut-fTn0rGqf%1tB-r$JTJH+|sRwlH^v~h7& zA*`d{&cVvoN$s4BFYfaXYOji%HTKeNrrG`md40^Ggu3h)d>s3{&coHY1Mp{pP|AWSItN*h$ z#{mdYI$9VBHNfUOi{siSog^xsCp@dnn#n!K*39un8Vj9-eyz?bQQT6N96|Pv_KwT+ zxF5aeqdvYK2&_@XO(C@hqxGRae2^e|wdNJ^)iVU#-XG0j4e4po{WY^!QV;ZSz7cMl zeXETs9S@KhX4tbL5UKl+T4i)edBh}D5P|BsQte25pzk~Vw$NVnUIz^=5T4)` z40;%uaoR#q;AK-lM&}y-_|kO{qI?*R??!O!gie=`hz$=k$4J(35~u=V3bMZ@QKKsQ zU!kEo@|2w}y^x3K(g)KBG!wtR;fJPz<~BD>YbP!#wna1LX^4w{q0VWq@4x|p8OaF1 z_Qp=y3H+M?5hF&cYyMNa*K`AF`!}aM87!;-N@66qK^l=wvX`$;C8DtZ?;cXyu;J|e zdHTgXUEZ#kqqkop5@$lZSRl+3NB~9r=m(&7DsSGwGhg{bSRqgBqUCL%uC(md3ASYk zFFPz9>q_9544N8pOIa4n>HM&qoo{TItu#=yU(b)j>cMl)XW&%izNmKZP$AjU=#*;$ zhn%%aK20lSkDkK+s7^*&{*@o?#5R?967&uL##@<9R@2F#i{!gU!L;fagkDb0fhGO> zubiCSFSId^*>nV*QQ4yN+~kLhL<2>X_B7Y&PAvppn}yEGlVOf)>$cMCNXO(^TyE-y zbaqO1LF;p*`A+P`5AR%r^H6?a4H5FMmZ?srn zUn*otTs%G>ClBzd^LP=Brm*r(85^$J7fp}#SE-cYB7Su)0WyRgKKDEC>nkU=+b6i+ zQ^wbw>gm{1_H#rSk|@Mth{Ey`1?LZc$GwOQYer$4X{HuGPt5 z`vpUC89ue5o2Z_Vp)=Hdt#>g{m_Ko8qFktz zX31pbD1cF=H$z9Mm9mTuZ0-CpMFpmd4YbYhNAr!bq&-j6S%L6fXS4v)j`6tVlH^hG zzk8QjHj!l~$`*Mw{k-GqQ?2D8->xKM!DDWbLX! z143LL&c$Lzb<5GPaHL6?zwtCp>?5$t%Ze7}N+4&Dkpn}jPBRPagrpM3Jh(0DxLt>~ zlU0m3_N?;CtYaBwCH5}q5h=@7Ehw5z(`VPPx3^Ecvat4i z2pJNETKKDt%NF@#&LwK9!)XZ#`d+-Tw6d~v7|yZQh;W?sRyP!z`dz0|ns~^O)*q3- z^Gg+;Q(H(xH!nr`f|P-Ud`+uMGc#N8HG)P?O5YWb08?fE$!RBJN>4reY+a3J&pDJj zmEl(s!^#_cnBnFh_EYeS2c2Gt$1AsX2r@b)|8#8N(y~)X{xKkuRB{RZNj0nW@ZC8M zXt!@$wfBhfRL=gvkmQU;5VksuZS3_tecb3kevJt~*t}xzK|u**&u_c8t;$`f@>+Z} ztnP(HPgRAYvXa^GG^%raLsNY-iq(qB!!n~A2&ykgZ2$hb0nx31P+1dEw^{f)QyJ(WliZ-brma3DMPJtV=Y;9ew zwA5~T>8T_AA?b{1LMAF9qI=u5l~1|w%Aos)Rg~LV%$D8T1V+ER9CLr`gtgnB9GaN(CsI^tYmMzMr;V)W3HP%Ge@dmRD~} ze}5QK#KC=qdL2hq$0nl0f_<-)hY@F_Y7DG6e? zOkxMe3_<%|QNNi-bsK;6rRjP(-dr^GIN$W6k0N*Ey`l{HD-REapl_^aKUq7^I!u#W z+Frp0aIugjV8B2pUgAF@oe_d_g*0ta6!B%8^Ja`}WGIxbDlL@z81}Ymyw%d%A@c_I zR^`3c;Bd==*U(Z@7-pq|xiE--`W2JQNZldt*}A=L%Ev& zzbMzY2jqV^*zY&sfAyn;692!Jc>k{%kWXE)70#YGbcGxnKp#))CfLHaJ)TaR*8T2Q zr;8N3jw{>PeiIl)eQd44GS{rUF!b@Wxho)hyUpW2xlR#pzOK?~Nh5(x5M7;W3fXkz z6Mj0W13fi?a8MAjuwb~J$;YgzeQ>6LN6fxgi*5|o0E)?Q#F4 z@{*mgb}u(K-nH$IkfSrc?=9&&)gpK|@i?y!>b>d-WuyqtAQCbe_^c?@b<%dXb^cRY z{Ql%@B{whSIRTw2&%)OS5>GDjVmFzub053v^uEF!uJO`Ooku3RR}&=+fzgtJbHq&)_yis zq<&#qx%}OQ6WnDc!v8XGzQ)y*-R9hntdeK(M^z-L^XrR)*xEmH(S#phy?HC|3fYFf zFx0izcwB6x8Pp!ru0z_NaMOXyiWQo^$fnl>A|~t)|Af> zC!n2{-u`(zVl}-;h`#4Ttnhr=64uE`vVfNEfvd)KZ$7R#>T?FM3~F=k?6~YZ*DuS~ zyP8qW+8?Zm*j#e}L{EZ#<6{>gLAJ?tVKspA5XQpX2-f0tzu~8-H$^{Z{s&zVnS=~n zc};-i_S}A3Fq2=8%T4&HGskRr32${0awef-VReIjLkgUwlYVV9%*sF$$w?tq+1z8$ z*@2=ytmmh$hv7n5^m(C~$4BBZeD9+1pU{=o{Z7BlSONDAtBx6BLV@$pY!(&CODrr6 z`46nmm!0hv_c%|)%T=P+pAXA4#?q(iiyqy;EsU5IzC0ket1eVeVXCd8^|#PH42P!d zF4tMw@EEm%mz{^5g)hQXR9ktyuS9H~-Q9op=Sk_XUXPDMoE*l^bJ5+~f4#e(4{A`Y zEZ?g0c)s?DgC&VK(QFq$(2$Rbu`v}Dm9cRyUi<2O>n>A@Z&kqld*77tXZ!i%=n8yq zN`}3hR}*F;FQk)}PBDDi7wb~2aH`BYs;?-*4er{q{ZsZA=kmC_1eR93hG9?SXW0W@ zL^qHByhITd6MYT!v3?Cl5tYUMK6(E=OM8dOV9eYtdJ4>}x%*b#qHHH4nI)&LAlQ1? zVcouKE1f9);skvWmEA*J9MS(24g<3X+$eXjrHXL1}`hKb9m^J07JvW^?}@i!1; zIlEm$p5fU+*}$hof+a|O+2iH24sw}?oK??*WYrjg{VEuCG`8~xe#>YtGN zcvo~fyR4u2ay+|^dwqw{jSD_@m;l+IvKHPg-5%R8@Mz^yC5dP^UFugA6kau{IZUy# zKAVe!K-sbP?$)=l=HloNj1^D~@N(_C+;Z#V`unFRxbAtct%E<$ZdK)NyuarMxpnl* zcwQ=`9`tIvxAa@+HDz47puh;Ki6syHzm#JN)PF$e0*99N4M}d$XoAoxZicT zTZd&{7>;AQRcE#DfBW>3ETz$(fE9?K4+4S2L(Y5sVECmZl+LEN6olhFk+qpRr!E$-X1a(?tc8S=g&h8Tc=rQDXhDHL+vX0;J{b@afK8t?N7@`^Q`yA zUY+C{ztfl9wa!QNp^Up7e|;`}pFV8vM|F>h<@)W0eA@;BxGN0G9pEr&Qpo>kzymfV z^rORn+X&{45dy>G8M#wi_;Gi$<6LHr8Lf{`Uw@h$)*>oq7CAvua^CHM{{WbjOwSWl zyltAN#f+f)uG-T4i$XdG`KYRxb^9S@fqWNo(dp8qm(cLspPg)9_OQK7u6q(}Lu-z# zcn*bjS7nrx?mO>Kbh6U$KvL@$JI5I#{+tZrvfqt;@uYDptm^e+KwZ>-}lJ}wGp)q$~;zW(ZFDHdW3Qb;?l%UpG^odKY^MWr=_Eio2o@@;q zwc;*CMxtVA0`O5#a-0KY4E@T6d!Il}*_N55X;O+12hEiQ6ol?jk&b%LOXExym;MRp z0$fc=i4!6)p$)me#oev5nI>yx<>yzw(Y4o>+nw$GeeR+AO9e>5a*6ff2}$w7NgyMLZ?^KwndWk%&AJN{aBaQ)pYL7gz8?UPjO zaBx2=wXiVodMfT0xQ4{Wu002HKc>1(eE8GuV6FP+`C45p zPVzj|)BfOv(Qgdoc?_$1HYm(oTuNf%t5A9p-l})*B3!63tb7O- zCL3>R^sy)sB3rc=LI2q!HRC z-A&(&ipypA%nyi_Aj{xnkSyJU2^!5_Q4iH$^Y}!|hCdIFWjWnZqRgQwJ zKo;^R*OO}-P?4DEgnam8Kk8`z;GRS_Z`Um0izVJmKNL6eat+$kTR%8g{$lj{+P$+4 z1oH762QeTDPW1NQf-yN2$#mVqmFRN41)ztUhb4Lagx_?ZMAp44?~Zn}EjoofQ>R(< zb{>l3ba0A)A_ERjlS@KSi_>7Io@XrMA~g#6+b0sZmzNWgZAH*4@-1F3tEquIb|sqvjKPa^TNYlI@fX45yvz z_ucKial18Jfo`(CFB(%7stgC&_Hd@eLME0vK%P$`+sYCY1j?MA!9Km+xQp}%^Z9Uq zCmcJQ*@cGK#&t7Ab2)wR9SvmqNf_ECfMK_2l^WOJK25UNu|xX2n5IU|dLf8`2?tPM zq97T(sQt;r2hZt5?~|)!`96vL*=8NT7d-a={Qk8dz|PIjLqkKg)wzKGU{DD%>&ks@ zc{<-{2{fn)uKb1UQ1Y5|KX6^AhY#J@E#3d2_h-)No5{vc%ogjb52K$o_9`DAmbBQF zJjAbgo&}p&7SJJd7^%mP>+8aAMKQa~=hN;5I{%=2uC`MlpB{VZ+7dZ&D6~MzMH8F| zrciIPQd#oL>!ZAoj&g3?u(Nq;VI=KLo#>NXuLyq(ZrIjU^>H`}>OMa|UUFH56X1&v zuE6g5Q^?A#wQk+Xr{i}%bb9W0S5dfD)@dMkH{Nh_>RYD83(jdX&VBE9x<3w%T^D)O zUN^l1i4P2YTZ3X@vD4Xi9v^o#_I=SN^ts8L12uZMOHLFPF(5`TLg&3%=9UOchT0wK zQC>rQ6CcBF^e%9EqUsF}$X|XHl=NE*wSpC&p!L^Xpqh>K&ZRq0_5VnqL(*r;?Q38t zgQo}s2pKWueg))n(Cc6CrDt_>aj0e72TZT3cU+ecE(mHTH`3F6+6t zi`@7fyJJqnDsjeDUQA3`+_agBRBRngF|v<72Z|NMW8va%8(bwrxg8C?brJ4gAs6O* zv4@9EMzTp$d;x@x4T1T`i4EPg+c|Vh9G{6FkXA+>_q3{2rP=nir?7G&J5~5pW{Z{8bHMy$XYxIz{`!rgX+l|s_N?M zs;aPUGHd#_jdxi~QT8wLbR4&bRS|BE&-+{LYl@N!*7nJFAjCn%@QDvs1kHb!)^MJm ze=pva#j)3T+}$CFPe&A^%S)}<$L1d%KTVlGMBvysxhwuNWSLD_ zopl1d66#?Mo!JbYToYu!nQXb9HF<*gCS^Sh&7>d7$IZ(VKJ6q#jEj(3UtPty_+MzM z%C0hkYW15vFLkHa44{WWC&M#~&j(I1X=HEk%jduv?fQ+e$eS5ZUuWAak}VQqfobNrK2P*6bCn)dl~A$8>mv;`cG@vGdmM&iAvP z`?WpT?uU-MkaI!S&!Uh0Z`>WJ@7wn$+}z!>1ol}c3^wh9oVg=(-3G43Q|A zuC>^YV_8g4oPszM4NeBdc&s0*^$mLll%Pqd4jQZ-M@Oq*zF&hw*f{R+bpMJt?$iAD zhH+1r(C1-jTqqe`qcQ`!aZrWfhN$Cq3w4KmpVb5A=WC&9Gn`J&Y{TeOil;yXiaOq~ z_V}9l5#E91Ko@aVMQcLWHod!L9m1bxTnQ_fhwcNT_PxS0>P|w>&pjLNLlJ_84zCjw z{XvgqnLVS`pR1&iJtTVs2#_EG7gZas&((|1I1G3df6o>=yl$jFna*(aCy03FyR4h} z|BBeGdKdm2OS?s-qrH`NA3Jn$@^+vl@wjSM(TCbB#%M4nVSoQQKwr7ud!!5*(sUup zDn7jBe=%(aVT;AvFP5rby7TX7x(GFRLUd8@dNjDK?U#_4z9r>rY`B=!506U2lNBj! z5l~%5>focaK2!9cy6o~n2etEZa4?vUWB7}DkfG~WB8O+>$)`HQR)k%hCy|LFwI@Zg z@VqmxkLHV|^yyNK7c3UqE*H$m#UYu@2h{E9mDLmFEe^tYe9p@d|_iGIwi-eSF?OLdO^Z3OzUV~_nCk&1$ zKMlcQQ2dxi>&do@;A;uk_xjO487I}6yCvED@LsdT&Omze*I%L9$JwOIoTF^W&e5!f zKlrE$J@$dh%%wguyZM?p%n)q?92d8i{JBfm`N5f0Tp?Wny3v&^gzd#>hJzzDY(`}X zzAta+S933^n_So;zBbEcu~Lj2-e$)&*X*MnWXk|3_~8D3NWLRRl8UO9@L@aj^NzbU z-mZtS2{-6qg@(SL%{GY8#Q*WCR?EY;b4mE|An&8go?%E=GYqk2hhmSeb=f{u`NgrG zXky)&iF^LBvS<6B?9p(8P}|V%TSSBq9<5aPuC*T8%%S{zR`siKCtZV@rp{=}K38LP zjv4jNL!?WUW!RkIV|q^RfT>F>LF~VUs;TSmt(A6aLaa))2khLtn_DwjYQ|&o>(F3r zAYof761jXv=-b!#h`PYnGls$To6J@I7w)4)HTBn7^yHxXc?4u_s{MDuY>RgYtJvqz z=5KO~&QxYY$n}k`O}9%>?zEtuL$sVfpbz~}REx3^Cxie|8Ckf1UkwsE^`5E&&nCK^ zJRq-HlXVcZ9dcB!6?v6la={w9wQk&xZQ}2@xa@S~(dBb$U4=naG)fM+Y_-@$guJ9+ zIjX;0p|#1e;KyYQ+SmC2h{|^6*x!-2t8!R(U&xzC9>6;OPreHp#L!1XNdgo9$neM5 zectCmFkkb4_!m`%mg&9vr4Hf1uY!z}pX#_cB|aINcE)tJ-+_FiWuw?&x5Vsf+`N$I zK=j5THGMy~A2497&^ff5arb|$0~A?o6VDTR=yTo?RwD`{ok%--T&6Dg z2=+b^1X|qwM>m-_8KL}d=l_&~pj?8+t`=(;U8YeWTIk-;--M=j58>wHz6V_fLXtl)5`=$6>ER$)}K&+L`lm zGPcx?1%)uHboqO|DqDVtP{4Z*Z?GTLT7TDNb!YwIlKc46?fs)f!xl5L#_B6j`AR$cPmZfWRpn3q+gG(CLYK>RxETf728xzVrqhTf zC6n`MOzs%rFs)blvtR=v(A{V^sqHb>BOho$5#?kjnd$q~DcD~f@lnc8{w5HqtQR3f zvv8(@ah47s8DuQQ(6M{lgfFga=B)1D*rm^g&st1zbtQ4*Lwv%L{NsZe?q1Q5_=PiKLeoC6JnKGX$IXsU?S|5E_B zeH4?UWf_|Q4~{FPBuxKk_bKA}3-59n6d@`=xV;p`FP)VvU|+pJ=(X0#OmwvLTk<~H zb!J}m+^(9xiWoa%+cU}EA$aWc236eH%NSB9h>PlIl7^Vf?^iK-&68K zl+XUELY-mOumWE-KpffU`28AsjPC}8`3{iYAbcJ#?X?dWDcaY7N5PhfNiGd^Nwv9d zc%x2>PL(Q?o?fM*Ovyu4)Kc2IWNN}Ela--U&(C+Y@Ycl5Epu`2Ht376^P8B~jEry1 z?Ve3FJ$uH1%GThjH-$FD(Ji)0uhP35RFoZmYBiaaHyyio`bFR-e?S?M(JreIr~7^wwhnlY;scBZD?~$^XS?~j;Cm}7t6RsJ0-hJ=?6km zA3k*(1_9GsB)WpaUv$e|K`gzIqtPRoZFOdIc9Af7C*ewd^D}}Dm#U!$`|ksyhVz3- z{tq)0HTF97YZZ)YS~kZ_Z~NJzK`oErq|h6eXff!Wa^VaU+gtUbF8> zMO?U<^pY4PZY{PIt@Xs$=9mBW<+hm8IAa&kR8CIxvBSrJ*BwubvpYUp;MG6(@N_HhBlt&CN!*zug4s% zUwvZ##*qwu!vH9nkNr!a2H79a-~-yo68+z!bx+zd`c||J-wdn$i{;!VkTBRkpzhniph&ZY)Nfh= zMelL_SC>s^%ke^BA4uZhJowRuynW@5{=1crcau-}u3b=#!zS zSCe~Yov(CJxedpt!`fT<-bPs^#ZGu`X?Awe*RnT$<~q8_Cuq8y;N9Rfu`K zRo?EYNGW*4u=%?)N$a`TA%gwJbW;Av8q`7MEHpHp4oMlOl{HSttwhPS64KHdO~)#y zD>5@riyAAx$fMgMXG+cG7j)G_U41k>H1<_0+rk-AA#UQLs*>%stF!Ew*m@_z6VUac62{N;O+~b5O&AM5d9o6df zbRM7|2-eat!y@Fivm1$R>wu`^T=FpSM{tP4TADB`x8LsG`>}sbXo59Cr^b9NtzuAH zKww$XPCq%V@zRxC zOJ;R;Vk=T-VrFga*o5Q#n#(~xo0rvYta9&6G~{z7v|PZJWQ#)U#$*=PH&!e zJ}s*r1jN>|P=+q}L}3sACHDW4P2`dBLzTbkLT~~M<#TbrTmK2tJvu#Uy>457{^;&^ zOgP@951rYWwK-aWHqR_C-cEctR+RC-Iy;j!@tu8`Gxz{?xh03BVWfT#DVd+qb9NFu z@2GW~9&TROef+uamF08H>mWPF3$2WH(`z+exjRGfq9wZ@`v8gL9f7IQ7sk? z(J#_7Xw&3Sqa{^}(t2=lwIJ=q+kjt03aO=+JV)$nV(R-axe=Fie^kUPVTbawifCaA zj&K=;8*cikz6vV;$lVb-dPUe1v@R+xvAz#_VW-`K!_~_aEl|Cbg zhUHX-PQ81V{}0${$hFMjd68<|Y zH8fDy&M~#R2?9cQD`8AxSt3V7E;X82yrj^rw9}lfh4EIMj2lC$c<$GI+yhhh-c79Y zA#k9sMq)*w8Ha@OnlY}0O)VUt`NrpDWQ8hIn=*%*BdL)hp)pY^qi+V?f=(M!20#ZB!lFX{CV=A&J|5`=3MxkWWAT1LrM-?|o zU*rq3 z3k!}=2Av|BOa+Y~>!Yw4g;A8$RI22OCvP zl)ZdpYycRlfAEs7my;|qwc5?%QPBJG&o9~u1#z6r>Vw5TOYAWmd5FHc#~h}LY+Gw4 ziGf^@HzFZVYMd!T)UBW;J&xgei)`rJU8Os@8$9s*avGa<*5WX_<#V3xo^ldMsH0rD zIs*&3`8I(^izO>#I8oD?TB$r12v}JFxYqY>XaV))E=~wjyi<(yww^>-a$IHOFq=WB zur6^=F8QWiss;etu8!~IF)}K1Et6i$x#LsQ4>U2&S$UuyGCf?J+HUx!^8SDi-z5W} z@gdlU-Tn$+unq5OfgL`Z=FTy+56oQmVOw+t(V;an2R6jzF@d4OLa%|tdVx=+Nf`C= zm5Jy?&(OpVmWfDy=b@jTN*pMNwy^*^#9e8ZjjW|Gv}%+ zrJjNX!Egf+AyDm3`#xU{VcrQb9}BS35@YbR_C+^V|A&iB=b3#wo-B3V%zFN9HW* z>64sF5#55c=?OV+S<-P#gIU~%545P}>@5uMzpKLPK^CE=!y0bUdK&I zUr|VrBf!__^561sJX+@T#T%X?(o@6tWL%5F1DG<%$Ql&6J3Sxil~I_sN!=6$j+D%= zGyizbnGLnZHs7I;O53jx`_pCfi99}h8cZj@Ai7_5@G(4?AAcY3B54BOWHES;Y_nYCR^l~UX?UyC!RR82#4u9*B&OmFf&?~hEP zT>1EBED5^gdJD#%AvoA70ruG>hC{O0-AJc+S;6F#DZ463ami=}$>Cfu@hmlz`l>ur zz^zx&{_9ch>JvXxGL5W?-|1u8QhsjctD{K_qfXRUjysL0;)>D7IVC;EBTl;E$lV{l z6SbOGO(vJr5!$I5H%1VYWzOHAq9;&L3~);d+$O4Wjeuo6N_Vm2f#t@ihH+FkQoy2& zzNC5>+=O9^mls_r?IAPti9>lPT$<_r@kwL=?dbrk(>_I9&ba(-1!!hA+mX%TUX-Y{ zT>8|?;kq^IzwVj8=Y5X56HGyG%C>vFJ@H$-6D0TmtoP%qcR^8C_~4sMA+i_~GbA z{^0(qOt@Jqfb0&_EuRIlcM(}3bk13}%_`6}XcvS~0|72ex`Cn6yULE*rzgKqk*iQB zb7s>{W(x$GEJpR-4BAn;gAmZ;r<5HVbt98kt?#7s-$S%>8@^+wPa1NiA?)wM1tiMS zSFLh5ZpGGVol+DQ0HX0?8$UnU2yX@;^Q*F?+}lRaVTQ>m=gLi)pGG0&2{{JZUAxDN#hWZ{5INcNZl^Cu z`gQ#6O>bD%RSn_^y>-BjS{;^i6lLFwFh(e%XOM}D@^B43X`A#moB4DVN?`V9ono83 z%wXq8(U2lqXGrL@+V2XV_+s7ePA!SMFRn|~n7W-f` zOa1T5fW%ePgAE{{VRrWC%KN!re_7-=t@Gxt1%xd%s$+xWy_Lmru9~oA;ryF~q4SY4xR2y@W4GT6R2y2+!LaLDy^kvR}x4^89zikjh ztyC7|?H4+EWT@M?4O1xaD3lRCXs5{K#Vuo~@?u*@N05X!vW%ORmlrp+5QNQYs@u`b zw2Gqv#eCXZ)@<6Ezy`^Hb)H{*o>Y!r8c-N$s}EcU^Q+ z0;19&NJ~hE0@8|rq;#irr*tezX{3=>>F(|>2}xD;Pf#2WWXP_ZeI5EVW`!pPVxp@~tu?mJrE2dIUX|k|~_xYYlTdKYa7hMu9f- z3qkq7f@}AQV^vTl`J*>>A4LuM))jF{X^V=W z31X)o#YKEE8)Z?F=94S}i$_A+ncDFt#RWZTXw;&;(S#N&mvJqpg?+3;`8l)YPG;m~mQQ@d^Q4&=h=1$*Gx0D^X=zto%M=g6udNj1d9sV=HIviV z(Mq*qtLb%dx6b?lT%N3`#pTSi2v7;i`hbyLoTuG93n$U=GSbn5QS>wYa6nagomisu z#AfPw?e8}<_*QhMO8bR6CbkX~-whAXvzO5!tow~|jrfi%)sqWDnHLf(56y9M8FH8k zbBo4{c|p1J9eovz;4NpUY8|OG`8e3&SO+VZ+TN%v91-$Gu70hn)eig>Vn%{cXcF2n z50vzcvueNdn%HH6%P!<7F7qFrj9VRZdrhsn$+fzThkHLvx;$4wPT9RhXhIZ+p0rqo z>^-lKR&-{Wa&dlXxxZ3EZ7zi&IWB_?l@UiUryolRHsy>&-cd+_(WP>TIhsP=m|zOi z_zYcz{Aa9lx%Q+%mL8_j;vqI1YMQLdI%@ZEWG};VE{CK^jPY7oWmKUB$$5c*JR2EUK%gGM8bp_II-oYnd#cTmOX4>%*59>i;Zq>!7HbTWPbl0lCuBlwWv9 zKrCp*1weVS#U6(nI?H;S8`u*gql~9yHOuuc;blPg0-R;89X4w?lI;6qRn2S9R4hfDlT2mazm9KYZ3TKeHcSxzzfBz)R1SE;vXN(1xl=`@b zZi(1)#Jp$4Us|v>c^WC1t=czJi+>-8ZD5So8AwbgVyB8WnQ8MJ!S#y5@5~uwX|Sez=muJxyaLN#DuC?CAFNjR~D()4@l3re)I{&e{#>UFM5A(HBL6 z#+Hum%!W$@)<#la+mFYSf+`Xe}0rYQ{?sQg^K8Ms1r|xwi zmnsv38DuByRlBw}?=hUg^I*Hoob3R^IUevx*IK3V+gDX2ZC@Q%xi`BG4cVIr@G+BE;I$s{hYS8KYZlNLD#_99Q+qmd}zusRRS*Y80*_nA_ zZF-1JJ$<`1SBQ!P3pPe3UM;olw>GKA$pXaolOz zwf6Qc{aHfAcfMks`P2IHVy|I$?5rOidTxKpF@L1ogY+)u_=I*;Dhh*xfWgn%j0qVp znGpkQ@%6tkh9O(glkePa=btE-?=Ga(2?o^e>I5BlA$W_Nf6a1-Gp0tfoTuVJi@5RI z>!?B=N8~=8H#_Q`ilf%3(Ay)S`wz9V=h9AP5~!kQkIH9JD@UQl^71gNk6lu0d$)Xh zlxc}quP$bRdkeH*rF(snvn4+oeM>kEJ2f7ku|To25=y-%s5-I5HO$Zv=WvhCd0%Us zZ`!72!G@K8*2u|D6{W*(AyFrePmu=l7VPgW7ZRG98@t&gJ&TYX$V7@g)A2lUu1X;< z*(GnEbAH<;B)LEO?zpr1Zp0?v^)$nAPKI}M1&*z|ipnu>y){SqS4~*y$^7$Ysw#Fu zlbcpEVK6MW2dJ9Qy~g2J3YYE%skj##*A@$x?__Ef?xlHh^mQ}}d~z<<@t@f{k##s} z!_XYm32kmRjugL_mdt$)-bxBv#qSp&V90< z{TlSUi>q%T4flsO$5leuz$RyPr%<5=bK_0)87bdfz%v)aW;l>ZEnn>_S1``V!2r`jP<#QXVP9*FOM1c0(PF*{DeXDNZ zUzJA%o6r;qJTyPR@Lr9P>IcD-`@7%D>eMZNt08p|bw+Hdn9{tx*u#|N9TdE6xiR>- z*jjtWdKCvjdw3oV3mZ*&$yOtmjEz#Xz`f?2#maqM(Q3~*PQaEAYI%bhBQ$k$&KEz6 zes+_eRIg}1be7>PiV&E-R|nU8`5ojIzm|4c5rdLVeqt=8E6Z0S9lxm6TQfkK6tspN%q-NTmsZcAo_+pV zH)AY$FN(@0Iv>vWc@Eccj=Cs+ANHdXo_AYG3DnwX)!joWUi+tK-`Ifj)ux#|A5nC-8Vu!W1M9q5OdV^gxep$Rf|*inyj*p-$8+O7Wa?6 zE+r10bibX=Aa=O&lN}6n_Bubj5`6N=?w9w#Pc_V zE!;~q)s-+?&R?H~Zf{@9E(kB9GJu^wV|Nm;wY{r2)FJ(;jQ zP5S8Qgbu>_6<4^M;@Q&AyB+2S3EG8NlAD74?t|+jZbv@+%ts!v8tATDbkQxb-fca( zYQ;&qmb2MUh68!;%*dbdvhKi#Q6W_!OW4$*#KKA@9bsH6D zmO5H3XK&S(U4bbd*bE@Ki&=XR$E!T(?K~%5j1wMoN_p|PrEuCkCqW2eEPAh$7fpY zsESaxpv;#0jnGpNmbjzoalfcwRk~S`T<`59>hj)TcI;`U9|&FBuOppJUN7EM&cGWK zU-e`xC3o*}amy45RKxZqru>>;p4lITP6y~aU0e1I`jHb@?>C(Pv64R%>4IG)E#N}4 zoSFOS4i*cWjvlkH?zzZ?5cptttuunR8vYrb?upa`C~Z=H}S}ZGZabnP)NU^FkYD6obo_<+x0bI6#*-c<)Lz z@&1Yh-kmqy{~MhD|1UoM|6Kl>6?!-)#B$tlo_E4(!g}VhQ_rIb535H;Ka;&$Ca#-A~}C_YtlG7oUMniD8pM3%l9jN$95{{XwYf^V9g4|(8}Ja08A$j! z{1KSDHo>;7e@4ZSh{@u;ej!U7E(0IMuhH(AV{YCpcSx&6+C*O%z20;s$6A`n>J$m( zM!k!*!-bT`7no!&8=t)c?P6LTh;_Oh;JYs_&(Q)GeLkP#xhy^vYxs)5o{6djuzT~0pm^OT13bC zJ2S8^F9>hT(E>LDZtY^yP}Y76?d@OAn2;Pm*wxXqb8x4b7_>vp^4kh?Cno4za5vrf zdZ}}<;(+MD1KzUwICbAd$imJOhpzVMowqE@nUmLj&v>ETqd&_QNP@m0cXyRTc#Rwz zmj{mBL)C+NIw62n@U_0|{AQ_078Y^&iV3p)0k`yk9>?Mw-Wc3?2pwFX_hIihQY@Z&)d(m! zF5m$Yjqudbb7BZcU#Cwn;b;7q{0l-G)=Drdww0M%^q9L~RVNy159S&Y`AbX=F(PT= zUk)J?o~G9yhTqgET4Q>QPhPPvfa1zCFMd-5Bnc$UVa)5VLR~Zaa4!8>tCpj?TKHk+ zr^iREJ}chjZ+UD9mT|w=8{H=?@NHOdUbiyQO1n9qpZVQXzwUW`yD#)xpFEZ5NkQ8B zg^&N!1Dm~5S>S!Sb$U9)a^)Q{d-~Ac!>VOn_wNks+E^FT+hFVzj%{V~O|INOE5FC^ z(!@ za=zjAu>6OAJ8R_M0QcM9M@=O+A!1h`#-*$wb-9)7M-4F_gr6LmI0t77@!wP}z+25u zV0@V%Q;pdG3-z9HX=*0-AmrW?vT3{|!fI0=aVHPN4sU+=EB@~U)gNXi^b^uPzT%^5 zX5Tv^=N6rsoM|VQ?j{oj|F`x^zrC3W4D?EER+ik6x|?h&b~DcwE^J;mD*tN{5WBfz zU4}20bHDlL>Fap5E_7|PSYz~WKVa{=z)W4YNw{11gsTH1hhVc3vx7(AwqyD@XDsZ{ z44o}V%!beXT|RKc28EVZmEb062nV2Wuv+Y5%H;Dr4D;U>po<%FQWmF)Eih|33J(z@ zW~k1?cXOZb;p=~<0?l(bgXW)68_vOK4m^aw+Vsq)nW$e6<1@Y|`CsdV4HazmzLX>< z!mGBuHRmCnTh-$IHOrg1NMC={@A>6qZ7X-So^>BZ7Neiu4g3A_h@k~Helk#BNJUlB zfz!{Le+}I7)_)}UJ$V|ZrtccPpG6x9^S`~Seyq+^dR-|<Po;NnZgOA3ZqIC7nMykjrI_ptI&h?zY+~oe zL_Rj$j?B%4O%Vy}7CEdB4kSEB5X00XX4SS<#gyzq) zod|{`-v_OR@m2F|A*;?$pI?JRQ(+fY`;|jii8>d5?tWPSAH9e;3WphVgW)M{_!F;3 z3xjvJC_%He@ENVcEq7H)25WVRR!ltM9ZaUu2ctLS@}K!%V?Z8NLe1OgUVEPVEAEXD zqTAk?fmi~!8s{fs(9Q#gLxgmG7@tm)j)nHrqx42qw%y1yyh4u`)9}*jqZB06@W#oX zj+KPpvqnEN4XTllzj@U?KTgxlim~KXc9Q*B2E|*dI~Z<}Mrs(s9S^6thb4?ln;gwS zSGLO9SQQOxVmm`+hiq3_vn>T7gqx11imb`k3%caxj@o;>Cl|=_qlU-PQt<-0SUS4B zAD?~{5?F+$mI_ye0`HaFUee*i_V9nG-)zA;1Ll*lg-s6yyN_4_dtl+}nDld=@yl%o z1`R7e2lK)1M+41%FNeHLM*9ie#F(0#eCF=z*qf|gq^~YZ=tSN_PKR?+5I^isqx0^q zuGuJiB$%PS0&wABS$>X(5XpYSD0<5gA^b3W02Pa8JqRAS;?AmdAd^lm@snl5Ll+@_ z7dBOW!M$JR$3X7JW8CK$Lgwhu^{5Tpjb`s_gPkY3H=`FGg5KhtvoSpKNDEbI{1X!x zYyw7|_JwPk>+wSDq>Ed+;nycrLknlWqA~BcmizTi80o(50zTicVPcyuBn>CxaiF;R@@70Q*goA%ND+cIn z*6KM|SD=^K2rkF+K1n>>K5tcM?^22ol7`RYzWBKSmzYe0U2Xk7+lhDgL~^`%S=3DK zo5VJBhV%-?HvWed!vm?G6bzj;7`j=Rxr1wiWcttEgKBUAi_E5`?fqh_>9Kn26k}S~ z?zz$L5Q`rZz0IF=dBy8dhcq$i*h3GI4pK~7u+R@>6*ZH%F!w#e;xw_=qRxs?)4!;l zhuiJ9%l_a!*O(b^Zm5&8C4vkWVA5Sj*s8MdwMwBG&&cxBzEOtsi*Te^)EN(?b$-Md zH{_uspClf)Vot+#HF`K@Ln$Nik4w^av!bVe~j65y2Yo8IMmsZ#ZO7tGG4`n+EM`*ca!suA1>*z zKRkm$0QH{yrXveQKG1HO#i00d(s7oB1Pxu>8#Ht&{*ZiGKF3|dRpT_cY+cKAAF6xT zSY@!VH?WFIIvK~;wH69ipe5_APwV8%bQy%jy49vC)aN8weQEHu#-13*Ctk_Nixv4+ zCpKjK9+&V+ZTuec)aL>(U60Qcz$qc`O-!M05a7xd(BR8KsOi`6P>+M4fb2`|%8d0i zm>R*Vg}cL~g_!1!UpX@68tsOt(7RMlnPCe!3|9G8Fp}igD^P`J4CWZ6Kkd_%-sqyD zBG!Y@hga4{UMCBlWuncq=VKrEVIOJYp2ichXnlEZGDuj@u79^Cd+p7QQ6GMuk&=`Y zyZ)Y?y&lr*!cv)hc{I}Vsmg=oaetr{h8Qg~# zgdnnjaI|v~AMqTBp2_|O1^ZephqWKAVc3)(Mi2ik)KPPrCoyzd;C@>$FFvQQbVm zcyS*Q*koG}60N#Qnxy>fgEGhP@o6~R8S-Sf?osFMv{AtgThzAm^1}#F+aqy|?5$r{ z1-CW5eufoAGp~u==^bNP@atMy3QTY>oIvCwib2T#KSfEFrc0H?FPMym=fGuJ#Mh6p)}2 zE(1rIl&LOTWco-8jH(S&s7pan-m0ul%{PX=vi5>^wS+n8IU#FatjgY?3iM%&X-MFe z;rQNIF9amq+X5G;Axa{FjxT_goR$Mu%^_swsW^)(&3m~_(ypZ_-r=|yb9}9UQVm__ zn^~ZBCXv#r>aZ?zS2LRcR?3yJ&*Pa3@UJvibo-U}X45mbhUG~cc*8FlZsx_3LTH}d zDVO&@YXs`qlXl(rOzGS!mXFoc5#cT@W^)&iOa3ViCCHULm*uH(Q^?dTynmfEVMs%4 zpJ>S<*Y}Bq7!63So9Sgmm%4nd^{-t{NHnACELGjlavz#)CJh}Q@GsQDM7M(9XahN* z$NHv$39tL5OH=XHk8u24sj8}bCW+jvH<@n=fueM@!9djfGK%xb=gPAKkFz_it}5B) z+6{gt^OQ?odBFNr-H@erT-Bi*-Dj-(-?oSQ#yGp(z&kBZIXh6@hOb$tuGfPjBI^t- z9LR^xQl=xS43845;VQqTrl$su_!sIpJ$1Iq2C{kGU7G4$yUWIm>UmvL*RK+*fjqbB zLdk@D=*V+!w{TY=-D)gbM^d}AIeOi-$+J7EA}sqxh8JizJqNx`Si^CWH0!~M`71bp z9M~Y`PVMQnl6hRg`L^y;vCLU1XD%bAKu3L5Sfe;MOWGScFCM&7g{%_Z&Y{$vI3L`!ZB;28-YD)_Wu{SC6 zU#h^!9>8|_;xepX4g>^m4bQD?hHaWzoN_yZ-i>-~WFEH+a)_`2rLKf_X+Qa1)8633 zAb|T9KsFk8{)Fe#9#Hv?a;I%#FuA>P1G;CEx=YZHZF4KqKn!8-Z1e?~B#qH#M>}g< z&lo)ekpzSl!{A;TY*x;TxPaCXq^^;OOcC4r2PaO+B=ea#B$*kMovgwK()42S9E?H| zVwWbmk~1=4kE9=B6JwaLCsNXLYf2zMnSGjh#!o^C9(hxE8|*lt_9H}aXb`;Ieg)h% z9ik1X!Q)EZujRyt(W3s~A<%9%!7~tF)0?93T#5-Kr?=`wZ{4qWfdakii>W~V+HP3U zUwJ{#f#|JdYF~+yRQle9G)95BJgJbWL?t9iCoesPfDuDFq?1yWzIS*V4WdxmeDQ`w z#E#40Pu_iZ{moNEP}f27Fu+Pd+ehp*A|zpAoHx~V+0uybt4=)UKUnc8aEmi^N{^Pa z_O_fqLpUi`{ELhV%Lg_TsGxjcPagqIQmmiWw#m1A9B;B_{6d`p4!m~#K8gp4&(x7a~Vtem_#qdV%E~qA=RI$&< zDSIG7IN&06eV-uUI%C)b)ORFU(#d9!OlqfMV0mE!) z#Ro$XYMC~lAmkQ5WDFVeIp<)(3|w`2{-_R!KjDyYLPDmNj`mE<%M!wZ$#|lm>%%#) zNPFkA>ZtMgY&~PAr#=eMf{CJqA<=*LwsU)VKwkN>I*IZbHadh?$owk0wy z;Ly|c+oSx9FI11S`P6zdxXdGCmVQ_hwk#rj6&JBr!CW4~gS4zMP+MXvhLcNc5% z%@dzlyujirWeAC~eW7f^Wy{6!j_!#g>064g4vf)Bk`u)=lH5j&5>R9y-f&2@jResy ze*l%uLQq5N6*UxogaThbd9U{n$26c^&tV82eEL;2b=fH+4*dv=S-K+mXXId5Q(!X-c0 zZ=a#YfH5m)RB=hGkfe|vt7d+3LJFi&-Mj_HjDq7K!@tm!%ZPt)x)(fv*y0i!jTKS~ zsJtr^2Dm;ULB2ThZKVu9X>m>}m5otRAz)VRP=Y&`V-!R@t)9*O>oG8ecwboy;q~@% zxNAE$`XTA@g^u3~;OCL&8rk`PI57U?hd;+VL<+?r#OT%^KN&7ew;!8Z8A^!GU>JsV zZda*4h7!c2X3n<4Za*PxmnAS8=*-44u1bg0`T^rt(&BQLYx2*e$_(=P#t$xe8QXn? z;s~U=pS2nmoWwl>7Z??VCIR_Ekb+3rJJrC+`kEg``F$EID61C?QOh+Jx$;0Nop{Vi zK!^$@_Zzpa!qRXgsH)GJx2|K))y01|=3{0A;@^b25=?nc6w}O)y z2r&R!V63b)*wxNindP@I>OB-wpvD_D&wP0hxcy6>W*j9}OQupVdk|nC`pA()OAUN` z%wBdG_v7(*urPbaTi!5a$aFwK+4bZ*3O;hIR-MgB#JVoYL-!}MI&85_oG60WLY1Bi z=EUC83=Hdec_%y=MBxDLzFwy^GhnfF2con<7Voga& zc}#pq?}X8FaXH~Q{J!c2AArNB%MEZ91vvh{-P(V)0(}Cz{rwNdeX>4QWkrO+$W*QO zO6wCLVS&KlJaVjb9Kf<&Tr(o;`k#xn55BjaxDw9G$Cj4-cmTEh1D9K5n6#|rFvES= zn`-n5BU^2s`U@5p|G2<>t3Bv@!o3(F+qrpI@q&HrgXPWT$L-Gxi#KclNBbuCk_o?* z>inL}i`v6kE2Y?>>lP4UZ#BQEs zth`JE;SQ74H3ARlBzu@O3ggc6ciB|7w|_W&diso)ol%HYLJTZW6FeSTj_NR)4}^#fpR@gObD64AGqc|)M!&_MgTD~lQt@&-G>9C+KWze}<7kBe~J&bJaA zY+`7C<*laKB+9r-_=-sOAUfWg~5p-zu79)*u6`_;)dMR^oPlw}@@F zn9YY=bnTBGR;07gb>qY{mnQ9ysU%j`i*G(Qi$<_b$iI6jiHqpLt+Wpn6yE4s?9O+9 z2af@S_&>oxewdrVbeZ;UtJ$!7MBfUG*3Xi&L0oit6KmUpU9p8j6GRr zpgtY^7tMiUrm-#>Gf=v==K3Gt=53-|cwqv!O>fue9Dw2iCS0r%Gq!aBpwaDLi5183 z;T3lcjn-KhO_z}tA`S3O;95!q_D(x9KT#9cb#`}GT{y{~x~pVLG!Wn)I!m7Vl3J(# z)`5HIXwC$bKWUd$^02us06Yqy?;rjlXHxa(xTZC^{N`^d1BKde7>Lj`^|};UGmCyL z5arPbbWday9ZdEE-0I+F;5MCjGXSpZtb*K)UcmDxAyv`q0wL(x4XeBs4wXUmg;Xah}Th!o-8s=$b zn&8Cjc>9ru?&Rh`zi(rk^PVod&3sv*N!{By!}Gx#Mum7w!MXA7BZ0!J$&7)d>NRoh zQv~6Sqr_h~$bG(?7ShgZyL zxD5QB9)Cw!>R=+3!3KLMa84o$F5Qp%pnxNT4Y0Wa5Yq32aj|@$e)tcDpM3Eb!)v(w zG(;T=6hQMAPWc`a0lg9*Qzx!%AHiv`kzkWb$4IWZU)lTNi}WLn_{=ygh`O*}8V|h$ z2~Z#{{zc8_J6QrGu?;jXG)79uuY*wE^@bQymAI?v&9Sg<7pPg2ehGcrp+n$}3@K0( z+hY+ZAcasu-bV=D-M!~Kj`Mz2S;Ie3BQ0;H$=E0&UA=cg^S%N%(^5`d3@1o#_ zsp--Z#>Teq;(PSoO2LRg(UzKqbmZR}DafxMAbWJ+ukePej+0rJJ-_w;(f;$BBI?9| zEgmy%7m?2FGddv`v8~sOT5AI1j$vHf+vFmG^xVVh8G*zG(FmAQkBCL}6CNl3LPGmC zWFveL;5}Fzxjxcv(5Wtf zq1Jr4W_X+Q2QZ42q*iX{6$ z)Za(Eni+eggon`bSogJ|38UwlU{|ONaWw1tkSCrT@tN}=OhFX%*hKs!9C39FekXOtSb2t= zUo1}5h#);CPWOQfUUgCE*H%)Xe@9E^BlYi}oF+COg8A_%f445%gvOo+6l$P`RE`tv z`WRYu#9`q{u)Ql#R`N5|JU{+Pbowthy>&d7^e~YMM;k=SSnX zYIP!t8t9zk_&mxi1ZWCWs^$*kU?ZL9m07`#7-1x@*LP>X6S;Cs%*ho_@;!b8j*w+y z5T``&E`1!v{Pib8!1eLdagMEDVOvFhq`jIUjhhi9A|Y&+SPTc4TXeqRAujn3Zarc=lEqZFJV7+hKQs^ znb~+rL`~w4P!2_&Yc}f9*!VL1@ofT?l2?67(=wSF5;>yfpvdn0{zyV?uhBS9KW3o6 zutJf7)9^r1iPM}q_7%%Q)3lGOH}5X zYoc;o+_0k8%ptUzj(0w)zyeUU?okuWQvYQH?fMA!__q|?+;Re4KF7rpKAyq{P z^qISqyC;hx?Q`78_e?CgNLCWL6WXOEDq6LCng|d?s!WtWTl-cDYysLb{m`iLUWgwh zHG}qRpEz28Mvd-_KP(>+h$kq-lb_FOHGEC%k=7evw*E{}YZ#s5_Vc}&Q*wP%=kEKL z^1{|X%_}=}t?npSlm9>$x0Mx^4E|oubKp2d?1=|EcYG5|d;n^8ls6u#p!Q=U(@6X% z2AjVH6eIx--oAY8&R@lQ`(@GOeq$5Zq;zmvFPd&u5&F**?zF~#B8&atJ=l*Gm?z&q z8+~H=?h|R%PHO`wDqp>qA40Ptp^kDv|5V!GZvI(MS0^@2jJef!x7#kQTz|KO<+byK zZ}(ellakPXt0eAIYBwfjR>s_pQT?zI$m~33Gdjuj>v1@Rc<=-;gzWP!MQ($TB_yIl zbb7PwEI@|;g*SQe9r)4Z9q)Edn<}O9oLU>b<94q%!_4}fDp9k|7D}ld+s*!QP&fi8 ziGTbKCG7%~lxf31cL%Aq!;Q=sosu`VmM@wH6+vxz|yG$gxS6bnvT@#w|AnrsOTC9TCmrKKJv zU~qS}JtvEeC%?t!T7;hfSnFVXXZS#R2Qk4_*8$IiiM5s$&us3jV*W9FwY>({e&7V~ zNMsXm$}~^H9Z&Dzb!7a==mg0ov4&L-+JoGx;+x~rwIXm0S9R}fbmHptVe5_q%d&Tc z@^$*%33udklJf)W1w9k4EaoZV2R|FejQA4WUBLIUR^qY?(?0;#ovd?|m=4w+@CjDQ z8pQapNk(*sGPquj}d0oB?0m5oVn!Bbk4@au$d(3nX_ z`MoUDoDSAYBKG?Th5a&7SWt#=e2Vy&Fam;?A*~&G4&};!tC5Y&GF75!Y$rd-WsW|$ zL|~1eWl>QC!H>b`Ui~-<6#l85E4S!XIt7Av#`EXnmIgNm^^9+1#3GQ_OJ{aj2)w`I z-Iv(FU{3Bd{gg3lNrM8#FxccKTCr(>U2O-aO*6;PThY*r%|7@@(UQ`pYZslQ1yJDM zm2`tD-Uo$ThRF9+rJjw^OQNGg{vs)vk$g(`hmsd3BnUS5^7o=RRC zbm&zsPDTOPfDB41jZ|hHP`bx3lKb%u0rpNz1T!7l;^X?cR(mKTG)^9Rg@zVhIzFky86U??X;tEXSmOHle(tRD+hl;A&>=)WaWq!uIMX z5;IkYesH;~8Wdd4sg~2xIcZES+KPYTq9$x_RY{|d&Bn4HVg5!;PrNd@zahJ>=;zw0 z32lLFU)aG0HhtE;>d%$sBx=VP7&1B#PxG&Rx2 zz|b~k`&P1|PAq~(WTtM@ej-EN7rwYIjgya}NV;o?Ah>+@@&QCo<%6dvEU8mrb7E+7 z4=YFFTQ2@D4HozV=-7!y--q4Aic#P3T@Y~l36iR{1+SPlb{wqU}*l)vyanNq(iVb*iQg6Llom@9`x6zFII~S;bBQGA@CKbedWLne%J<2;LN;lZas; zuwBS3T@XrY%SkBV#}(#3%VCnETVGRWl#1hyqWbnlg|TyDkqApTM>38(hN;+=jY8fi zjvz+@qKL_73^C8Mz#xoeCwZ-)z{~zzSHLGz>P2R(oT7H5;;Oz61&w_sm+C_(gICca zPpx{m2m8bPAai0Qox$A0akoal-`*57haKO2@o=EWAwPd167LR6A!pQmolT!qWzt=Q z-O@DkvqpHm@`$7oIWh#iYSnkQxwiWtl1kR+D!I?0q=Es_D3p%QuiR2KdMrvsNv}8% zg|YLLStdC~dc06mX-6MDfw!4jmM0fU;M)(z-l7~PO~XZT^ppbmklmf0(Xd(Pf^oUR zV%t&@tQhH7?HCE9Upus(Y{MKz_VO&L*I;tI5C_7K#~;x*a@2L&2&8Wj6`29L9SE7Z>zYUT0jMXIG$&crvXk%fv|DK|r z!^g1bjIA%f>Fx{93;mmlHisa+-A`p2ex0pYII%@vUrB*Y)ECQuse}v{Dn^EMZa=1n zHH(g%j3I5w8bS5j2(2;+rN)ht7kq=-3rnYL$NDs!)8dW+#0l=7|u%Aa~owMZrM&BTC_iybIZvz5A! z-g0NGcBZ2Xwt+XXD(Q_rq`%vmI-G_D$RDQ!3SL+^V_OyG=5VQNGrjJMnV$7Xu~&=Y zut)x+#Fs;K+e2-?Mq3^K9({GB%@>d8eZIP`)sfw)GSNN6j_E^Y4Wjj&;*ou;idr?_ zsC>tZ3t|+6J2wQ-8Hc#~Zvz9t6*CS~!Z5$>T{6t}py;EJGG#olPhw)(*1e>V-!DOR z{14_H#jseNk6Mwfex26S#yJ)x&ne{1?J>ZScWRew7sox_$jgyj!KSY7MBEi&svxR1m)?U6tS63R&Oj4Sq%hIZV zTyspFuA#oOodW3YubY*oLr(dSuHsNB=g}I-$kzeL*0la(jmGTBJ3t)*!cQ|g?sg>d z6g1?n;amt#n(p}3wcE{?8J%7Is>lclV{_ZuW`C>Ri?jZY#B(SB=1-|0Gp(q)W4Z@y zn67?I+=&9XP-*x18reNpzZJFEuMcQeok%-VNCv260q?7V^3Ut;)1Mn+QmfX)Cx`zD zxRY6+j{t_0I_Tvt5elsw=E?LXP^cUNa+S&6`{Y#|3?H6fEgIUXm4yV z9aUI})GD!Hn*lE9iubeCV>F-v|5jWZGzV{;3hm5i*a^yLx|vp{R~6-|=_jaew){H+c_!e4XtL z9fU^^vc3B}WW>;G`Zya^ByZGN zvDGX2qTg=!z3v#H{C!aK7-~QUUDb8Q?Gr-&U~Oct*n3$ivYBNG$23LsUiN53Z}1Bb z1t1Oe5hqyysyH@!#uprg!|$H?n-W#3)Kn51xh-YP2AYxs=pxI;fVgIi_E znn{oNHQo4vfzS5MQXYfLvPf&?tz&pG#iFVQu#WLUZ4AkZFHa<{JApsOqVJVjJD z_)}*^a1VM_6!V;U4HzJ_I5rF})p8XM8Ru};zXX({+-OVg3kDptST1bhyu2Te;GZqK z-m}lp+6(Law|Kd#|94(4lKh=KHC_LXzX`FZqfseFX2J_;X4LAzEM*2h|uGs-}lzlLdbPhFO#!0(*2MYNxCf_ zvhdQpM!bvpr?h{rF)~?lsPpdkPblLl5#&TW92LaU^goe^l#|Yn)wehxpyv~lTahGLIZ0~sMnvz}{H^daLX*D!egc+7w1g^qlPZvH&d;4#AFEXh zr=U^Lh?dFk(j`qvNYVm!4%gn|&!|@!GV#8Y#tEes;dRjDTjKXy>^zW@l#!3TH+r{W zBJ?*gObaH9E4n7z1%~+VLV`PriyowBX+I&E*|W$jP>ugBV4(Z=^l$TB_W1vZWcn{D ztZZib|Vfl@UUyucc_Kq}7IVk=Y>%RHXGTP;g%&axG}6JtsK%+2=qFcL zXgUlmkyPI7lBIX<9p3o}Fyg+Ddaj7KV)*p=)JdgPzuLBz+Z}uXjTC6q!wr1on4(Aj zBzD$i^j4#PWB>5DKQD}{zI~S_EswuOgXlWBazc5>tYl`_x|l!TDf=DQfvBfd7~lJ= zCsX(T(bCLsV0h65vU(UO;;`4o+5VLZ-b)(A5H8hfd?6$x`r2dfYq&h2`)n-Fwvv?He$SP5lao-5u>w6gFc%Xva0)oilOra|3YbizmVKq$wYCL zh(dqya%E>CSae%D)rZ)4b~Kj#FZTxSYmeWpG7=epSsU4^YK^}C=EKjgMHOR8N=XIp z2t+vUlEYHbt)-5@bbHd$jm37QFnZcyo#TrUIiL!qD!AONLXGZ)!f+oeWCD+=Q{BWgnA# zIt&(**I9iX=4(5?J*gZs)^oc0lUtwktp%lG@j}1&svaggtAxd&WLz+P6yQQ6bhWf7 zr&SYI7D!OgKca?=b+}BuO)XLL$UyYHC^`*!%&)NVMR^lKn)v;GRh{PG zZ@kXWs{MdNQg23ke+`i&!%2WhWc8H@7vW2(rC-tIdF+&~V+En&(;t*blYKbjnJ3?r z1tUX2r?I$+i-e(OH-`dIhN~M-bBaoSQ4cZ-<;Vj^!U9{*kEYIMI4CXZ`S(vw&qwAo zmHZovTy8G)$T=Q7eK*KF6fY${p`j{Y)f770DEj=lsFmUl~P>kc_T|C#6ni6ib9c>za0YL_Z`9H zS~@jsZ|C&)mUb9P?aZIEr^iV%O($%oIc21?8WiRZ zKPhDSx)LNcKKq5)j!*j)tBgtnL?JQKF*(6U$~4@LV-sJS_Z^rWqX+TJGm@9J)NPrk zcedIBi2{F#?>9{}NV>5pZamI{iRTha{;AOiHdLxi{ouu9>wDfLzog&h#5<5os*X*} z@F;vAGryq>ZRLf)IN>^ zf1tXcA%Z-LvhpfF-K!6Iy4f-7J8mw~6K)VrSe#dN-Z0S?datc{;fc7nW!JrUt$g{= zaXX~vYy{~a<>K>tx0}!5yK}6z#4}{52Mf3)?Zgu$_lndyG!>;MkdeL{t~rT@Y`mey zMyC>q8Jwkv3PeW0rhXpZkU;G#l7YR6e;nLsLwhB{)*)BUsfn<}Vr)QA&W>uA<{hy{ z{=3Rky7MfZcYx$&{d)4k?P+p(i1s8ieL`57ymo(6&I~XMhZzNCtSwjSnmf`(M!6^! zyPJEd;}bjh^6+uN-LJAwTMuz;@T+{ilElmi6A1xn|VLHAKwq}`{_4xX8vc+%yZ^B zXXc#e{|vHudv)2}`@HeE-n17K>AJKkv@v6OLQbV_{0i6lraoh*?v*nZ#|;2ta5$WO zMpEXjz=K4*NA5#`Z3)q^#wj;3iOtQ-hUuXKwh0$(LlcBvRw?wnTg>0a)^@U=9<8e@ zCK`!XqV5dqyiT#Ad6pwJ;OWg;#g6y}e7Iawn8Hl}7Uo#>`%`5TbF-fIqg;Q%O!my# zGc6JMeSrZta6h)k82r^-X#3zur%gyuzp9AUSD{}ew~!FbOMbN{6JD6$m06S6URcJlf3cb++|mXfXyD%T&sbDU8@3{KWy|50|jjFnpae zLvWPzk8L?OJJdgpR{oT?^~hIMUl5MLeL-u^;cZ5E5{PM?HKU5s_0`h(ar@~ig`+3U zoJ|$5jHBR%<@t&=70QH)#(1*3i79NCk{G0KXh4`?w|WwkY_bcqUKs8E8Xk7^Du~+} zZH3AKhZ4dhxCaWawM}->vWqVc@w(;gp!2m@yL{45H zF}CY#mA?BgO!eAe4;I$omv!@cDkq=^>ebWZDdpon`Gzx18#r_@MgU?Uv`t`S|MXYo=Ksab7(~$Jb4>aodv+J4v;{(Vk%dyUCLBmh5{ztK+T z72z_z$~gN`#1R*n9XL8@DqD^&dB*~nJy;cx(TG48H}f6Uo_Z~9<>gNB#Ez8S`YYD3 zwp+bhC1GNIS9hm*&Xv(7-SRNB^CjO3T(i=L0)d6rLl7Swkl*)mgpQQ zn@eDJjR4n@7h~`7l@s_dGTZS$;wF>ImYw$EssEI*Ioq3nT`eIi`L%ULhnt+d4-ZYG@H6t~`iPf; z4woU9w?gZ2c+f-SK175w!;bL+Gd9z(Qz|}NW0fO^fSRXAcV=_3u>>1}!AZ_eT4?HL zN_m-qSv}4kS$|(ZhH+0DP+p3UEo&d8q_BV>`2fSw&6ky_jl&Mrwu!6=y@)SR^`O?$lbxh`kHMKJcp@*;f@eV|qG{J0KBPg=U2wcPM#i0?ro zi_qOjxZ(}MLVHZ_V4#~<4i<)w$MDnk12#88duXa*rk%?R>1o@P+-Iz3-Zky!1-$TYLaRUn#z^L$s-d@;NPvY;Jp8yORXuPsT{}4T zXaznHR@M1fd=Js`#CUSXO{N;j$076_>-GUQejAvXJj)uKRFtQSB%-1Ea2d(Q)?1rG zw*xZ0;g79i4J@Cc9sSJCVwxK9MNb|mNqloW`Da?*JS)V~Ksyq-RNa2(zIqr-A@gU0kGDEwR zm_`ejMt&?KuQ`fI7qz(X8s6)KmeNJJU`?NCM+K&r7qi2t34RtM^w3{*_^M5?Be5N_QKg_LK9-h9 z3pHP#NH&*Aj@3*&qd?U7l7Uk({zB2zju%|p1I-Eg{7F?KX?=?vOoy3OO(mflDD_+b zbigl1riY9rW;eK(h@g2qE&=3iP^^gvn;+u)4h<;&&fUi{H`~Bztz${bUpB1@5U)aR{kjAcQGreYZ;vlQ}L>ybn)8&LnE%= zx~3OM^y%6k+bJLk4C#PSP;MZSGW7C6W)}DBKS9Dh=%+4G!!?sCQW^2vf$q9$xlSV$ z39*TYR`bNOqlHC=xA8tTIklQKW?fuQ|yqZnmhuAHMdeAn+1CfyYWN z%~bmjXF`XwB_yrR`@8k zw8BGRXLlycR;v(H*0qYLn||?wcsEfKSK8b6+7TK)8`3P?L(W_8U6T#Ynk-Ys=Auv@ z$^xUp0|u+bi2K4=#;#eW&QM&E5i+}EpK{;d=7iGb`eD(0?A%b<6{(f|ZzHli-)gA~ zVNJfJg;iD0Ks4W|J%B3AfA8)|k4w~945QEDg$rq~=c5>(Wd1aKL}%ba+MCnM4BTU< zGBaRud!K`WY^7x(2IPEtK@7N#y^CVt?@uD<4E#rUw71)SN+lMmDKkd*J{3lutV General Settings ) +# `arn:aws:cognito-idp:::userpool/` +# - User Pool Client ID ( Cognito -> App Integration -> Application Client Settings ) +# `` +# - Domain Name ( Cognito -> App Integration -> Domain Name) +# `` +# - OAuth Scopes ( Cognito -> App Integration -> Application Client Settings ) +# `[x] openid` +# - OAuth Flows ( Cognito -> App Integration -> Application Client Settings ) +# `[x] Authorization code grant` +# - Callback URL(s) ( Cognito -> App Integration -> Application Client Settings ) +# `https://./oauth2/idpresponse` +# +# - Related Kubernetes service/application +# + +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: # app.example.com + namespace: # default + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/tags: Environment=,Owner=::userpool/","UserPoolClientId":"","UserPoolDomain":""}' + # ACM certificate ARN for your SSL domain + alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:::certificate/ +spec: + rules: + # If you are using ExternalDNS, this will become your applications FQDN + - host: + http: + paths: + # This first path should perform an ssl-redirect as below + - path: /* + backend: + serviceName: ssl-redirect + # Configured via the redirect settings in the annotations + servicePort: use-annotation + - path: + backend: + serviceName: + servicePort: diff --git a/docs/examples/echoservice/echoserver-deployment.yaml b/docs/examples/echoservice/echoserver-deployment.yaml new file mode 100644 index 000000000..716f48bd0 --- /dev/null +++ b/docs/examples/echoservice/echoserver-deployment.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: echoserver + namespace: echoserver +spec: + selector: + matchLabels: + app: echoserver + replicas: 1 + template: + metadata: + labels: + app: echoserver + spec: + containers: + - image: gcr.io/google_containers/echoserver:1.4 + imagePullPolicy: Always + name: echoserver + ports: + - containerPort: 8080 diff --git a/docs/examples/echoservice/echoserver-ingress.yaml b/docs/examples/echoservice/echoserver-ingress.yaml new file mode 100644 index 000000000..4cc73c7a6 --- /dev/null +++ b/docs/examples/echoservice/echoserver-ingress.yaml @@ -0,0 +1,18 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: echoserver + namespace: echoserver + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/tags: Environment=dev,Team=test +spec: + rules: + - host: echoserver.example.com + http: + paths: + - path: / + backend: + serviceName: echoserver + servicePort: 80 diff --git a/docs/examples/echoservice/echoserver-namespace.yaml b/docs/examples/echoservice/echoserver-namespace.yaml new file mode 100644 index 000000000..8a319129e --- /dev/null +++ b/docs/examples/echoservice/echoserver-namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: echoserver diff --git a/docs/examples/echoservice/echoserver-service.yaml b/docs/examples/echoservice/echoserver-service.yaml new file mode 100644 index 000000000..46f159ff5 --- /dev/null +++ b/docs/examples/echoservice/echoserver-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: echoserver + namespace: echoserver +spec: + ports: + - port: 80 + targetPort: 8080 + protocol: TCP + type: NodePort + selector: + app: echoserver diff --git a/docs/examples/external-dns.yaml b/docs/examples/external-dns.yaml new file mode 100644 index 000000000..fdb42fed1 --- /dev/null +++ b/docs/examples/external-dns.yaml @@ -0,0 +1,64 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: external-dns +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: external-dns +rules: +- apiGroups: [""] + resources: ["services"] + verbs: ["get","watch","list"] +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","watch","list"] +- apiGroups: ["extensions"] + resources: ["ingresses"] + verbs: ["get","watch","list"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["list"] +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: external-dns-viewer +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: external-dns +subjects: +- kind: ServiceAccount + name: external-dns + namespace: default +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns +spec: + selector: + matchLabels: + app: external-dns + strategy: + type: Recreate + template: + metadata: + labels: + app: external-dns + spec: + serviceAccountName: external-dns + containers: + - name: external-dns + image: bitnami/external-dns:0.7.1 + args: + - --source=service + - --source=ingress + - --domain-filter=external-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones + - --provider=aws + - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization + - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both) + - --registry=txt + - --txt-owner-id=my-identifier diff --git a/docs/guide/controller/configurations.md b/docs/guide/controller/configurations.md index 56dca1aee..ca8c5681a 100644 --- a/docs/guide/controller/configurations.md +++ b/docs/guide/controller/configurations.md @@ -1 +1,93 @@ -TODO: describes the controller configurations, i.e. the controller flags \ No newline at end of file +# AWS Load Balancer controller configuration options +This document covers configuration of the AWS Load Balancer controller + +## AWS API Access +To perform operations, the controller must have required IAM role capabilities for accessing and +provisioning ALB resources. There are many ways to achieve this, such as loading `AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY` as environment variables or using [kube2iam](https://github.com/jtblin/kube2iam). + +Refer to the [installation guide](installation.md) for installing the controller in your kubernetes cluster and for the minimum required IAM permissions. + +## Setting Ingress Resource Scope +You can limit the ingresses ALB ingress controller controls by combining following two approaches: + +### Limiting ingress class +Setting the `--ingress-class` argument constrains the controller's scope to ingresses with matching `kubernetes.io/ingress.class` annotation. +This is especially helpful when running multiple ingress controllers in the same cluster. See [Using Multiple Ingress Controllers](https://github.com/nginxinc/kubernetes-ingress/tree/master/examples/multiple-ingress-controllers#using-multiple-ingress-controllers) for more details. + +An example of the container spec portion of the controller, only listening for resources with the class "alb", would be as follows. + +```yaml +spec: + containers: + - args: + - --ingress-class=alb +``` + +Now, only ingress resources with the appropriate annotation are picked up, as seen below. + +```yaml +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: echoserver + namespace: echoserver + annotations: + kubernetes.io/ingress.class: "alb" +spec: + ... +``` + +If the ingress class is not specified, the controller will reconcile Ingress objects without the ingress class specified or ingress class `alb`. + +### Limiting Namespaces +Setting the `--watch-namespace` argument constrains the controller's scope to a single namespace. Ingress events outside of the namespace specified are not be seen by the controller. + +An example of the container spec, for a controller watching only the `default` namespace, is as follows. + +```yaml +spec: + containers: + - args: + - --watch-namespace=default +``` + +> Currently, you can set only 1 namespace to watch in this flag. See [this Kubernetes issue](https://github.com/kubernetes/contrib/issues/847) for more details. + +## Controller command line flags + +!!!warning "" + The --cluster-name flag is mandatory and the value must match the name of the kubernetes cluster. If you specify an incorrect name, the subnet auto-discovery will not work. + +|Flag | Type | Default | Description | +|---------------------------------------|---------------------------------|-----------------|-------------| +|aws-api-throttle | AWS Throttle Config | [default value](#Default throttle config ) | throttle settings for AWS APIs, format: serviceID1:operationRegex1=rate:burst,serviceID2:operationRegex2=rate:burst | +|aws-max-retries | int | 10 | Maximum retries for AWS APIs | +|aws-region | string | [instance metadata](#Instance metadata) | AWS Region for the kubernetes cluster | +|aws-vpc-id | string | [instance metadata](#Instance metadata) | AWS VPC ID for the Kubernetes cluster | +|cluster-name | string | | Kubernetes cluster name| +|enable-leader-election | boolean | true | Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager. | +|enable-pod-readiness-gate-inject | boolean | true | If enabled, targetHealth readiness gate will get injected to the pod spec for the matching endpoint pods. | +|enable-shield | boolean | true | Enable Shield addon for ALB | +|enable-waf | boolean | true | Enable WAF addon for ALB | +|enable-wafv2 | boolean | true | Enable WAF V2 addon for ALB | +|ingress-class | string | | Name of the ingress class this controller satisfies | +|ingress-max-concurrent-reconciles | int | 3 | Maximum number of concurrently running reconcile loops for ingress | +|kubeconfig | string | in-cluster config | Path to the kubeconfig file containing authorization and API server information | +|leader-election-id | string | aws-load-balancer-controller-leader | Name of the leader election ID to use for this controller | +|leader-election-namespace | string | | Name of the leader election ID to use for this controller | +|log-level | string | info | Set the controller log level - info, debug | +|metrics-bind-addr | string | :8080 | The address the metric endpoint binds to | +|service-max-concurrent-reconciles | int | 3 | Maximum number of concurrently running reconcile loops for service | +|sync-period | duration | 1h0m0s | Period at which the controller forces the repopulation of its local object stores| +|targetgroupbinding-max-concurrent-reconciles | int | 3 | Maximum number of concurrently running reconcile loops for targetGroupBinding | +|watch-namespace | string | | Namespace the controller watches for updates to Kubernetes objects, If empty, all namespaces are watched. | +|webhook-bind-port | int | 9443 | The TCP port the Webhook server binds to | + + +### Default throttle config +``` +WAF Regional:^AssociateWebACL|DisassociateWebACL=0.5:1,WAF Regional:^GetWebACLForResource|ListResourcesForWebACL=1:1,WAFV2:^AssociateWebACL|DisassociateWebACL=0.5:1,WAFV2:^GetWebACLForResource|ListResourcesForWebACL=1:1 +``` + +### Instance metadata +If running on EC2, the default values are obtained from the instance metadata service. diff --git a/docs/guide/controller/how-it-works.md b/docs/guide/controller/how-it-works.md new file mode 100644 index 000000000..c8c04e524 --- /dev/null +++ b/docs/guide/controller/how-it-works.md @@ -0,0 +1,44 @@ +# How AWS Load Balancer controller works + +## Design + +The following diagram details the AWS components this controller creates. It also demonstrates the route ingress traffic takes from the ALB to the Kubernetes cluster. + +![controller-design](../../assets/images/controller-design.png) + +### Ingress Creation + +This section describes each step (circle) above. This example demonstrates satisfying 1 ingress resource. + +**[1]**: The controller watches for [ingress +events](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-controllers) from the API server. When it +finds ingress resources that satisfy its requirements, it begins the creation of AWS resources. + +**[2]**: An +[ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html) (ELBv2) is created in AWS for the new ingress resource. This ALB can be internet-facing or internal. You can also specify the subnets it's created in +using annotations. + +**[3]**: [Target Groups](http://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html) are created in AWS for each unique Kubernetes service described in the ingress resource. + +**[4]**: [Listeners](http://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html) are created for every port detailed in your ingress resource annotations. When no port is specified, sensible defaults (`80` or `443`) are used. Certificates may also be attached via annotations. + +**[5]**: [Rules](http://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-update-rules.html) are created for each path specified in your ingress resource. This ensures traffic to a specific path is routed to the correct Kubernetes Service. + +Along with the above, the controller also... + +- deletes AWS components when ingress resources are removed from k8s. +- modifies AWS components when ingress resources change in k8s. +- assembles a list of existing ingress-related AWS components on start-up, allowing you to + recover if the controller were to be restarted. + +### Ingress Traffic +AWS Load Balancer controller supports two traffic modes: +* Instance mode +* IP mode + +By default, `Instance mode` is used, users can explicitly select the mode via `alb.ingress.kubernetes.io/target-type` annotation. +#### Instance mode +Ingress traffic starts at the ALB and reaches the Kubernetes nodes through each service's NodePort. This means that services referenced from ingress resources must be exposed by `type:NodePort` in order to be reached by the ALB. +#### IP mode +Ingress traffic starts at the ALB and reaches the Kubernetes pods directly. CNIs must support directly accessible POD ip via [secondary IP addresses on ENI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html). + diff --git a/docs/guide/controller/installation.md b/docs/guide/controller/installation.md index 93152dd0f..7938fbc29 100644 --- a/docs/guide/controller/installation.md +++ b/docs/guide/controller/installation.md @@ -1 +1,69 @@ -TODO: describes how to install the controller. \ No newline at end of file +# AWS Load Balancer Controller Installation guide + +## Via Helm +Follow the instructions in [aws-load-balancer-controller](https://github.com/aws/eks-charts/tree/master/stable/aws-load-balancer-controller) helm chart. + +## Via Yaml manifests + +### Migrating from AWS ALB Ingress controller +If AWS ALB Ingress controller is installed, refer to [migrating from v1 to v2](../upgrade/migrate_v1_v2.md) + +!!!warning "" + AWS ALB Ingress controller must be uninstalled before installing AWS Load Balancer controller. + +!!! Note + Existing Ingress resources do not need to be deleted for migration. + +### IAM permissions +The controller runs on the worker nodes, so it needs access to the AWS ALB/NLB resources via IAM permissions. The + IAM permissions can either be setup via IAM roles for ServiceAccount or can be attached directly to the worker node IAM roles. + +#### Setup IAM for ServiceAccount +1. Create IAM OIDC provider + ``` + eksctl utils associate-iam-oidc-provider \ + --region \ + --cluster \ + --approve + ``` +1. Download IAM policy for the AWS Load Balancer Controller + ``` + curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v2_ga/docs/install/iam_policy.json + ``` +1. Create an IAM policy called AWSLoadBalancerControllerIAMPolicy + ``` + aws iam create-policy \ + --policy-name AWSLoadBalancerControllerIAMPolicy \ + --policy-document file://iam-policy.json + ``` + Take note of the policy ARN that is returned + +1. Create a IAM role and ServiceAccount for the Load Balancer controller, use the ARN from the step above + ``` + eksctl create iamserviceaccount \ + --cluster= \ + --namespace=kube-system \ + --name=aws-load-balancer-controller \ + --attach-policy-arn=arn:aws:iam:::policy/AWSLoadBalancerControllerIAMPolicy \ + --approve + ``` +#### Setup IAM manually +If not setting up IAM for ServiceAccount, apply the IAM policies from the following URL at minimum. +``` +https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v2_ga/docs/install/iam_policy.json +``` + +#### Upgrading from ALB ingress controller +If migrating from ALB ingress controller, grant [additional IAM permissions](../../install/iam_policy_v1_to_v2_additional.json). + +### Install cert-manager +- For Kubernetes 1.16+: `kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.0.2/cert-manager.yaml` +- For Kubernetes <1.16: `kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.0.2/cert-manager-legacy.yaml` + +### Download and apply the yaml spec +- curl -o https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v2_ga/config/samples/install_v2_0_0.yaml +- Edit the saved yaml file, go to the Deployment spec, and set the controller --cluster-name arg value to your EKS cluster name +- Apply the yaml file kubectl apply -f install_v2_0_0.yaml + +!!!note "" + If you use iamserviceaccount, it is recommended that you delete the ServiceAccount from the yaml spec. Doing so will preserve the eksctl created iamserviceaccount if you delete the installation. diff --git a/docs/guide/controller/subnet_discovery.md b/docs/guide/controller/subnet_discovery.md index d327274f2..61b3dafec 100644 --- a/docs/guide/controller/subnet_discovery.md +++ b/docs/guide/controller/subnet_discovery.md @@ -1 +1,30 @@ -TODO: describes how to do subnet auto discovery. \ No newline at end of file +# Subnet Auto Discovery +AWS Load Balancer controller auto discovers network subnets for ALB or NLB by default. ALB requires at least two subnets across Availability Zones, NLB requires one subnet. +The subnets must be tagged appropriately for the auto discovery to work. The controller chooses one subnet from each Availability Zone. In case of multiple tagged subnets in +an Availability Zone, the controller will choose the first one in lexicographical order by the Subnet IDs. If you use `eksctl` or an Amazon EKS AWS CloudFormation template to + create your VPC after March 26, 2020, then the subnets are tagged appropriately when they're created. For more information about the Amazon EKS AWS CloudFormation VPC templates, + see [Creating a VPC for your Amazon EKS cluster](https://docs.aws.amazon.com/eks/latest/userguide/create-public-private-vpc.html). + +## Public subnets +Public subnets are used for internet-facing load balancers. These subnets must have the following tags: + +| Key | Value | +| --------------------------------------- | --------------------- | +| `kubernetes.io/role/elb` | `1` or `` | + +## Private subnets +Private subnets are used for internal load balancers. These subnets must have the following tags: + +| Key | Value | +| --------------------------------------- | --------------------- | +| `kubernetes.io/role/internal-elb` | `1` or `` | + + +## Common tag +Both the public and private subnets must be tagged with the cluster name as follows: + +| Key | Value | +| --------------------------------------- | --------------------- | +| `kubernetes.io/cluster/${cluster-name}` | `owned` or `shared` | + + `${cluster-name}` is the name of the kubernetes cluster diff --git a/docs/guide/ingress/spec.md b/docs/guide/ingress/spec.md new file mode 100644 index 000000000..c9322f830 --- /dev/null +++ b/docs/guide/ingress/spec.md @@ -0,0 +1,31 @@ +# Ingress specification +This document covers how ingress resources work in relation to The AWS Load Balancer Controller. + +An example ingress, from [example](../../examples/2048/2048-ingress.yaml) is as follows. + +```yaml +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: "2048-ingress" + namespace: "2048-game" + annotations: + kubernetes.io/ingress.class: alb + labels: + app: 2048-nginx-ingress +spec: + rules: + - host: 2048.example.com + http: + paths: + - path: /* + backend: + serviceName: "service-2048" + servicePort: 80 +``` + +The host field specifies the eventual Route 53-managed domain that will route to this service. + +The service, service-2048, must be of type NodePort in order for the provisioned ALB to route to it.(see [echoserver-service.yaml](../../examples/echoservice/echoserver-service.yaml)) + +For details on purpose of annotations seen above, see [Annotations](annotations.md). diff --git a/docs/guide/integrations/external_dns.md b/docs/guide/integrations/external_dns.md index 17498c843..35baca30d 100644 --- a/docs/guide/integrations/external_dns.md +++ b/docs/guide/integrations/external_dns.md @@ -1 +1,67 @@ -TODO: \ No newline at end of file +# Setup External DNS +[external-dns](https://github.com/kubernetes-incubator/external-dns) provisions DNS records based on the host information. This project will setup and manage records in Route 53 that point to controller deployed ALBs. + +## Prerequisites +### Role Permissions +Adequate roles and policies must be configured in AWS and available to the node(s) running the external-dns. See https://github.com/kubernetes-incubator/external-dns/blob/master/docs/tutorials/aws.md#iam-permissions. + +## Installation +1. Download sample `external-dns` manifest + + ```bash + wget https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.0.0/docs/examples/external-dns.yaml + ``` + +2. Edit the `--domain-filter` flag to include your hosted zone(s) + + The following example is for a hosted zone `test-dns.com`: + + ```yaml + args: + - --source=service + - --source=ingress + - --domain-filter=test-dns.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones + - --provider=aws + - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization + - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both) + - --registry=txt + - --txt-owner-id=my-identifier + ``` + +3. Deploy external-dns + + ```bash + kubectl apply -f external-dns.yaml + ``` + +4. Verify it deployed successfully. + + ```bash + kubectl logs -f $(kubectl get po | egrep -o 'external-dns[A-Za-z0-9-]+') + ``` + + Should display output similar to the following: + ``` + time="2019-12-11T10:26:05Z" level=info msg="config: {Master: KubeConfig: RequestTimeout:30s IstioIngressGateway:istio-system/istio-ingressgateway Sources:[service ingress] Namespace: AnnotationFilter: FQDNTemplate: CombineFQDNAndAnnotation:false Compatibility: PublishInternal:false PublishHostIP:false ConnectorSourceServer:localhost:8080 Provider:aws GoogleProject: DomainFilter:[test-dns.com] ZoneIDFilter:[] AlibabaCloudConfigFile:/etc/kubernetes/alibaba-cloud.json AlibabaCloudZoneType: AWSZoneType:public AWSAssumeRole: AWSBatchChangeSize:4000 AWSBatchChangeInterval:1s AWSEvaluateTargetHealth:true AzureConfigFile:/etc/kubernetes/azure.json AzureResourceGroup: CloudflareProxied:false InfobloxGridHost: InfobloxWapiPort:443 InfobloxWapiUsername:admin InfobloxWapiPassword: InfobloxWapiVersion:2.3.1 InfobloxSSLVerify:true DynCustomerName: DynUsername: DynPassword: DynMinTTLSeconds:0 OCIConfigFile:/etc/kubernetes/oci.yaml InMemoryZones:[] PDNSServer:http://localhost:8081 PDNSAPIKey: PDNSTLSEnabled:false TLSCA: TLSClientCert: TLSClientCertKey: Policy:upsert-only Registry:txt TXTOwnerID:my-identifier TXTPrefix: Interval:1m0s Once:false DryRun:false LogFormat:text MetricsAddress::7979 LogLevel:info TXTCacheInterval:0s ExoscaleEndpoint:https://api.exoscale.ch/dns ExoscaleAPIKey: ExoscaleAPISecret: CRDSourceAPIVersion:externaldns.k8s.io/v1alpha CRDSourceKind:DNSEndpoint ServiceTypeFilter:[] RFC2136Host: RFC2136Port:0 RFC2136Zone: RFC2136Insecure:false RFC2136TSIGKeyName: RFC2136TSIGSecret: RFC2136TSIGSecretAlg: RFC2136TAXFR:false}" + time="2019-12-11T10:26:05Z" level=info msg="Created Kubernetes client https://10.100.0.1:443" + ``` + +## Usage +1. To create a record set in the subdomain, from your ingress which has been created by the ingress-controller, simply add the following annotation in the ingress object specification and apply the manifest: + + ```yaml + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + + # for creating record-set + external-dns.alpha.kubernetes.io/hostname: my-app.test-dns.com # give your domain name here + ``` + +2. Similar entries should appear in the ExternalDNS pod log: + + ``` + time="2019-12-11T10:26:08Z" level=info msg="Desired change: CREATE my-app.test-dns.com A" + time="2019-12-11T10:26:08Z" level=info msg="Desired change: CREATE my-app.test-dns.com TXT" + time="2019-12-11T10:26:08Z" level=info msg="2 record(s) in zone my-app.test-dns.com. were successfully updated" + ``` diff --git a/docs/guide/tasks/cognito_authentication.md b/docs/guide/tasks/cognito_authentication.md index 7a823aec4..041a4189b 100644 --- a/docs/guide/tasks/cognito_authentication.md +++ b/docs/guide/tasks/cognito_authentication.md @@ -1 +1,28 @@ -TODO: cognito auth \ No newline at end of file +# Setup Cognito/AWS Load Balancer Controller + +This document describes how to install AWS Load Balancer Controller with AWS Cognito integration to minimal capacity, other options and or configurations may be required for production, and on an app to app basis. + +## Assumptions + +The following assumptions are observed regarding this procedure. + +* ExternalDNS is installed to the cluster and will provide a custom URL for your ALB. To setup ExternalDNS refer to the [install instructions](../integrations/external_dns.md). + +## Cognito Configuration + +Configure Cognito for use with AWS Load Balancer Controller using the following links with specified caveats. + +* [Create Cognito user pool](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html) +* [Configure application integration](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-configuring-app-integration.html) + * On step 11.c for the `Callback URL` enter `https:///oauth2/idpresponse`. + * On step 11.d for `Allowed OAuth Flows` select `authorization code grant` and for `Allowed OAuth Scopes` select `openid`. + +## AWS Load Balancer Controller Setup + +Install the AWS Load Balancer Controller using the [install instructions](../controller/installation.md) with the following caveats. + +* When setting up IAM Role Permissions, add the `cognito-idp:DescribeUserPoolClient` permission to the example policy. + +## Deploying an Ingress + +Using the [cognito-ingress-template](../../examples/cognito-ingress-template.yaml) you can fill in the `` variables to create an ALB ingress connected to your Cognito user pool for authentication. diff --git a/docs/guide/tasks/migrate_legacy_apps.md b/docs/guide/tasks/migrate_legacy_apps.md new file mode 100644 index 000000000..e34a455e5 --- /dev/null +++ b/docs/guide/tasks/migrate_legacy_apps.md @@ -0,0 +1,42 @@ +# Migrating From Legacy Apps with Manually Configured Target Groups + +Many organizations are decomposing old legacy apps into smaller services and components. + +During the transition they may be running a hybrid ecosystem with some parts of the app running in ec2 instances, +some in Kubernetes microservices, and possibly even some in serverless environments like Lambda. + +The existing clients of the application expect all endpoints under one DNS entry and it's desirable to be able +to route traffic at the ALB to services running outside the Kubernetes cluster. + +The actions annotation allows the definition of a forward rule to a previously configured target group. +Learn more about the actions annotation at +[`alb.ingress.kubernetes.io/actions.${action-name}`](../ingress/annotations.md#actions) + +## Example Ingress Manifest +```yaml +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + namespace: testcase + name: echoserver + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/actions.legacy-app: '{"Type": "forward", "TargetGroupArn": "legacy-tg-arn"}' +spec: + rules: + - http: + paths: + - path: /v1/endpoints + backend: + serviceName: legacy-app + servicePort: use-annotation + - path: /normal-path + backend: + serviceName: echoserver + servicePort: 80 +``` + +!!!note + The `TargetGroupArn` must be set and the user is responsible for configuring the Target group in AWS before applying + the forward rule. + diff --git a/docs/guide/tasks/ssl_redirect.md b/docs/guide/tasks/ssl_redirect.md index b28ed5211..39b571d1d 100644 --- a/docs/guide/tasks/ssl_redirect.md +++ b/docs/guide/tasks/ssl_redirect.md @@ -1 +1,46 @@ -TODO: ssl redirect \ No newline at end of file +# Redirect Traffic from HTTP to HTTPS + +We'll use the [`alb.ingress.kubernetes.io/actions.${action-name}`](../ingress/annotations.md#actions) annotation to setup an ingress to redirect http traffic into https + + +## Example Ingress Manifest +```yaml +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + namespace: default + name: ingress + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:xxxx:certificate/xxxxxx + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' + alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}' +spec: + rules: + - http: + paths: + - path: /* + backend: + serviceName: ssl-redirect + servicePort: use-annotation + - path: /users/* + backend: + serviceName: user-service + servicePort: 80 + - path: /* + backend: + serviceName: default-service + servicePort: 80 +``` + +!!!note + - `alb.ingress.kubernetes.io/listen-ports` annotation must at least include [{"HTTP": 80}, {"HTTPS":443}] to listen on 80 and 443. + - `alb.ingress.kubernetes.io/certificate-arn` annotation must be set to allow listen for HTTPS traffic + - the `ssl-redirect` action must be be first rule(which will be evaluated first by ALB) + +## How it works +By default, all rules specified in ingress spec will be applied to all listeners(one listener per port) on ALB. + +If there is an redirection rule, the AWS Load Balancer controller will check it against every listener(port) to see whether it will introduce infinite redirection loop, and **will ignore that rule for specific listener.** + +So for our above example, the rule by `ssl-redirect` will only been applied to http(80) listener. diff --git a/docs/guide/walkthrough/echo_server.md b/docs/guide/walkthrough/echo_server.md index bbbae3750..5c59806ba 100644 --- a/docs/guide/walkthrough/echo_server.md +++ b/docs/guide/walkthrough/echo_server.md @@ -1 +1,358 @@ -TODO: echo server walk through \ No newline at end of file +# walkthrough: echoserver + +In this walkthrough, you'll + +- Create a cluster with EKS +- Deploy an alb-load-balancer-controller +- Create deployments and ingress resources in the cluster +- Use [external-dns](https://github.com/kubernetes-incubator/external-dns) to create a DNS record + - This assumes you have a route53 hosted zone available. Otherwise you can skip this, but you'll only be able to address the service from the ALB's DNS. + +## Create the EKS cluster +1. Install `eksctl`: https://eksctl.io + +2. Create EKS cluster via eksctl + + ```bash + eksctl create cluster + ``` + + ```console + 2018-08-14T11:19:09-07:00 [ℹ] setting availability zones to [us-west-2c us-west-2a us-west-2b] + 2018-08-14T11:19:09-07:00 [ℹ] importing SSH public key "/Users/kamador/.ssh/id_rsa.pub" as "eksctl-exciting-gopher-1534270749-b7:71:da:f6:f3:63:7a:ee:ad:7a:10:37:28:ff:44:d1" + 2018-08-14T11:19:10-07:00 [ℹ] creating EKS cluster "exciting-gopher-1534270749" in "us-west-2" region + 2018-08-14T11:19:10-07:00 [ℹ] creating ServiceRole stack "EKS-exciting-gopher-1534270749-ServiceRole" + 2018-08-14T11:19:10-07:00 [ℹ] creating VPC stack "EKS-exciting-gopher-1534270749-VPC" + 2018-08-14T11:19:50-07:00 [✔] created ServiceRole stack "EKS-exciting-gopher-1534270749-ServiceRole" + 2018-08-14T11:20:30-07:00 [✔] created VPC stack "EKS-exciting-gopher-1534270749-VPC" + 2018-08-14T11:20:30-07:00 [ℹ] creating control plane "exciting-gopher-1534270749" + 2018-08-14T11:31:52-07:00 [✔] created control plane "exciting-gopher-1534270749" + 2018-08-14T11:31:52-07:00 [ℹ] creating DefaultNodeGroup stack "EKS-exciting-gopher-1534270749-DefaultNodeGroup" + 2018-08-14T11:35:33-07:00 [✔] created DefaultNodeGroup stack "EKS-exciting-gopher-1534270749-DefaultNodeGroup" + 2018-08-14T11:35:33-07:00 [✔] all EKS cluster "exciting-gopher-1534270749" resources has been created + 2018-08-14T11:35:33-07:00 [✔] saved kubeconfig as "/Users/kamador/.kube/config" + 2018-08-14T11:35:34-07:00 [ℹ] the cluster has 0 nodes + 2018-08-14T11:35:34-07:00 [ℹ] waiting for at least 2 nodes to become ready + 2018-08-14T11:36:05-07:00 [ℹ] the cluster has 2 nodes + 2018-08-14T11:36:05-07:00 [ℹ] node "ip-192-168-139-176.us-west-2.compute.internal" is ready + 2018-08-14T11:36:05-07:00 [ℹ] node "ip-192-168-214-126.us-west-2.compute.internal" is ready + 2018-08-14T11:36:05-07:00 [✔] EKS cluster "exciting-gopher-1534270749" in "us-west-2" region is ready + ``` + +## Setup the AWS Load Balancer controller +1. Refer to the [installation instructions](../controller/installation.md) to setup the controller + +1. Verify the deployment was successful and the controller started. + + ```bash + kubectl logs -n kube-system $(kubectl get po -n kube-system | egrep -o aws-load-balancer-controller[a-zA-Z0-9-]+) + ``` + + Should display output similar to the following. + + ``` + {"level":"info","ts":1602778062.2588625,"logger":"setup","msg":"version","GitVersion":"v2.0.0-rc3-13-gcdc8f715-dirty","GitCommit":"cdc8f715919cc65ca8161b6083c4091222632d6b","BuildDate":"2020-10-15T15:58:31+0000"} + {"level":"info","ts":1602778065.4515743,"logger":"controller-runtime.metrics","msg":"metrics server is starting to listen","addr":":8080"} + {"level":"info","ts":1602778065.4536595,"logger":"controller-runtime.webhook","msg":"registering webhook","path":"/mutate-v1-pod"} + {"level":"info","ts":1602778065.4537156,"logger":"controller-runtime.webhook","msg":"registering webhook","path":"/mutate-elbv2-k8s-aws-v1beta1-targetgroupbinding"} + {"level":"info","ts":1602778065.4537542,"logger":"controller-runtime.webhook","msg":"registering webhook","path":"/validate-elbv2-k8s-aws-v1beta1-targetgroupbinding"} + {"level":"info","ts":1602778065.4537594,"logger":"setup","msg":"starting manager"} + I1015 16:07:45.453851 1 leaderelection.go:242] attempting to acquire leader lease kube-system/aws-load-balancer-controller-leader... + {"level":"info","ts":1602778065.5544264,"logger":"controller-runtime.manager","msg":"starting metrics server","path":"/metrics"} + {"level":"info","ts":1602778065.5544496,"logger":"controller-runtime.webhook.webhooks","msg":"starting webhook server"} + {"level":"info","ts":1602778065.5549548,"logger":"controller-runtime.certwatcher","msg":"Updated current TLS certificate"} + {"level":"info","ts":1602778065.5550802,"logger":"controller-runtime.webhook","msg":"serving webhook server","host":"","port":9443} + {"level":"info","ts":1602778065.5551715,"logger":"controller-runtime.certwatcher","msg":"Starting certificate watcher"} + I1015 16:08:03.662023 1 leaderelection.go:252] successfully acquired lease kube-system/aws-load-balancer-controller-leader + {"level":"info","ts":1602778083.663017,"logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"targetGroupBinding","source":"kind source: /, Kind="} + {"level":"info","ts":1602778083.6631303,"logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"targetGroupBinding","source":"kind source: /, Kind="} + {"level":"info","ts":1602778083.6633205,"logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"ingress","source":"channel source: 0xc0007340f0"} + {"level":"info","ts":1602778083.6633654,"logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"ingress","source":"channel source: 0xc000734140"} + {"level":"info","ts":1602778083.6633892,"logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"ingress","source":"kind source: /, Kind="} + {"level":"info","ts":1602778083.663441,"logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"ingress","source":"kind source: /, Kind="} + {"level":"info","ts":1602778083.6634624,"logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"ingress","source":"kind source: /, Kind="} + {"level":"info","ts":1602778083.6635776,"logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"service","source":"kind source: /, Kind="} + {"level":"info","ts":1602778083.6636262,"logger":"controller-runtime.controller","msg":"Starting Controller","controller":"service"} + {"level":"info","ts":1602778083.7634695,"logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"targetGroupBinding","source":"kind source: /, Kind="} + {"level":"info","ts":1602778083.7637022,"logger":"controller-runtime.controller","msg":"Starting workers","controller":"service","worker count":3} + {"level":"info","ts":1602778083.7641861,"logger":"controller-runtime.controller","msg":"Starting Controller","controller":"ingress"} + {"level":"info","ts":1602778083.8641882,"logger":"controller-runtime.controller","msg":"Starting Controller","controller":"targetGroupBinding"} + {"level":"info","ts":1602778083.864236,"logger":"controller-runtime.controller","msg":"Starting workers","controller":"targetGroupBinding","worker count":3} + {"level":"info","ts":1602778083.8643816,"logger":"controller-runtime.controller","msg":"Starting workers","controller":"ingress","worker count":3} + ``` + +## Deploy the echoserver resources + +1. Deploy all the echoserver resources (namespace, service, deployment) + + ```bash + kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.0.0/docs/examples/echoservice/echoserver-namespace.yaml &&\ + kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.0.0/docs/examples/echoservice/echoserver-service.yaml &&\ + kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.0.0/docs/examples/echoservice/echoserver-deployment.yaml + ``` + +1. List all the resources to ensure they were created. + + ```bash + kubectl get -n echoserver deploy,svc + ``` + + Should resolve similar to the following. + + ```console + NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE + svc/echoserver 10.3.31.76 80:31027/TCP 4d + + NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE + deploy/echoserver 1 1 1 1 4d + ``` + +## Deploy ingress for echoserver + +1. Download the echoserver ingress manifest locally. + + ```bash + wget https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.0.0/docs/examples/echoservice/echoserver-ingress.yaml + ``` + +1. Configure the subnets, either by add annotation to the ingress or add tags to subnets. This step is optional in lieu of auto-discovery. + + !!!tip + If you'd like to use external dns, alter the host field to a domain that you own in Route 53. Assuming you managed `example.com` in Route 53. + + - Edit the `alb.ingress.kubernetes.io/subnets` annotation to include at least two subnets. + ```bash + eksctl get cluster exciting-gopher-1534270749 + ``` + + ```console + NAME VERSION STATUS CREATED VPC SUBNETS SECURITYGROUPS + exciting-gopher-1534270749 1.10 ACTIVE 2018-08-14T18:20:32Z vpc-0aa01b07b3c922c9c subnet-05e1c98ed0f5b109e,subnet-07f5bb81f661df61b,subnet-0a4e6232630820516 sg-05ceb5eee9fd7cac4 + ``` + + ```yaml + apiVersion: extensions/v1beta1 + kind: Ingress + metadata: + name: echoserver + namespace: echoserver + annotations: + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/subnets: subnet-05e1c98ed0f5b109e,subnet-07f5bb81f661df61b,subnet-0a4e6232630820516 + alb.ingress.kubernetes.io/tags: Environment=dev,Team=test + spec: + rules: + - host: echoserver.example.com + http: + paths: + ``` + + - Adding tags to subnets for auto-discovery(instead of `alb.ingress.kubernetes.io/subnets` annotation) + + you must include the following tags on desired subnets. + + - `kubernetes.io/cluster/$CLUSTER_NAME` where `$CLUSTER_NAME` is the same `CLUSTER_NAME` specified in the above step. + - `kubernetes.io/role/internal-elb` should be set to `1` or an empty tag value for internal load balancers. + - `kubernetes.io/role/elb` should be set to `1` or an empty tag value for internet-facing load balancers. + + An example of a subnet with the correct tags for the cluster `joshcalico` is as follows. + + ![subnet-tags](../../assets/images/subnet-tags.png) + +1. Deploy the ingress resource for echoserver + + ```bash + kubectl apply -f echoserver-ingress.yaml + ``` + +1. Verify the aws-load-balancer-controller creates the resources + + ```bash + kubectl logs -n kube-system $(kubectl get po -n kube-system | egrep -o 'aws-load-balancer-controller[a-zA-Z0-9-]+') | grep 'echoserver\/echoserver' + ``` + + You should see similar to the following. + + ```console + {"level":"info","ts":1602803965.264764,"logger":"controllers.ingress","msg":"successfully built model","model":"{\"id\":\"echoserver/echoserver\",\"resources\":{\"AWS::EC2::SecurityGroup\":{\"ManagedLBSecurityGroup\":{\"spec\":{\"groupName\":\"k8s-echoserv-echoserv-4e1e34cae5\",\"description\":\"[k8s] Managed SecurityGroup for LoadBalancer\",\"tags\":{\"Environment\":\"dev\",\"Team\":\"test\"},\"ingress\":[{\"ipProtocol\":\"tcp\",\"fromPort\":80,\"toPort\":80,\"ipRanges\":[{\"cidrIP\":\"0.0.0.0/0\"}]}]}}},\"AWS::ElasticLoadBalancingV2::Listener\":{\"80\":{\"spec\":{\"loadBalancerARN\":{\"$ref\":\"#/resources/AWS::ElasticLoadBalancingV2::LoadBalancer/LoadBalancer/status/loadBalancerARN\"},\"port\":80,\"protocol\":\"HTTP\",\"defaultActions\":[{\"type\":\"fixed-response\",\"fixedResponseConfig\":{\"contentType\":\"text/plain\",\"statusCode\":\"404\"}}]}}},\"AWS::ElasticLoadBalancingV2::ListenerRule\":{\"80:1\":{\"spec\":{\"listenerARN\":{\"$ref\":\"#/resources/AWS::ElasticLoadBalancingV2::Listener/80/status/listenerARN\"},\"priority\":1,\"actions\":[{\"type\":\"forward\",\"forwardConfig\":{\"targetGroups\":[{\"targetGroupARN\":{\"$ref\":\"#/resources/AWS::ElasticLoadBalancingV2::TargetGroup/echoserver/echoserver-echoserver:80/status/targetGroupARN\"}}]}}],\"conditions\":[{\"field\":\"host-header\",\"hostHeaderConfig\":{\"values\":[\"echoserver.example.com\"]}},{\"field\":\"path-pattern\",\"pathPatternConfig\":{\"values\":[\"/\"]}}]}}},\"AWS::ElasticLoadBalancingV2::LoadBalancer\":{\"LoadBalancer\":{\"spec\":{\"name\":\"k8s-echoserv-echoserv-d4d6bd65d0\",\"type\":\"application\",\"scheme\":\"internet-facing\",\"ipAddressType\":\"ipv4\",\"subnetMapping\":[{\"subnetID\":\"subnet-01b35707c23b0a43b\"},{\"subnetID\":\"subnet-0f7814a7ab4dfcc2c\"}],\"securityGroups\":[{\"$ref\":\"#/resources/AWS::EC2::SecurityGroup/ManagedLBSecurityGroup/status/groupID\"}],\"tags\":{\"Environment\":\"dev\",\"Team\":\"test\"}}}},\"AWS::ElasticLoadBalancingV2::TargetGroup\":{\"echoserver/echoserver-echoserver:80\":{\"spec\":{\"name\":\"k8s-echoserv-echoserv-d989093207\",\"targetType\":\"instance\",\"port\":1,\"protocol\":\"HTTP\",\"healthCheckConfig\":{\"port\":\"traffic-port\",\"protocol\":\"HTTP\",\"path\":\"/\",\"matcher\":{\"httpCode\":\"200\"},\"intervalSeconds\":15,\"timeoutSeconds\":5,\"healthyThresholdCount\":2,\"unhealthyThresholdCount\":2},\"tags\":{\"Environment\":\"dev\",\"Team\":\"test\"}}}},\"K8S::ElasticLoadBalancingV2::TargetGroupBinding\":{\"echoserver/echoserver-echoserver:80\":{\"spec\":{\"template\":{\"metadata\":{\"name\":\"k8s-echoserv-echoserv-d989093207\",\"namespace\":\"echoserver\",\"creationTimestamp\":null},\"spec\":{\"targetGroupARN\":{\"$ref\":\"#/resources/AWS::ElasticLoadBalancingV2::TargetGroup/echoserver/echoserver-echoserver:80/status/targetGroupARN\"},\"targetType\":\"instance\",\"serviceRef\":{\"name\":\"echoserver\",\"port\":80},\"networking\":{\"ingress\":[{\"from\":[{\"securityGroup\":{\"groupID\":{\"$ref\":\"#/resources/AWS::EC2::SecurityGroup/ManagedLBSecurityGroup/status/groupID\"}}}],\"ports\":[{\"protocol\":\"TCP\"}]}]}}}}}}}}"} + {"level":"info","ts":1602803966.411922,"logger":"controllers.ingress","msg":"creating targetGroup","stackID":"echoserver/echoserver","resourceID":"echoserver/echoserver-echoserver:80"} + {"level":"info","ts":1602803966.6606336,"logger":"controllers.ingress","msg":"created targetGroup","stackID":"echoserver/echoserver","resourceID":"echoserver/echoserver-echoserver:80","arn":"arn:aws:elasticloadbalancing:us-west-2:019453415603:targetgroup/k8s-echoserv-echoserv-d989093207/63225ae3ead3deb6"} + {"level":"info","ts":1602803966.798019,"logger":"controllers.ingress","msg":"creating loadBalancer","stackID":"echoserver/echoserver","resourceID":"LoadBalancer"} + {"level":"info","ts":1602803967.5472538,"logger":"controllers.ingress","msg":"created loadBalancer","stackID":"echoserver/echoserver","resourceID":"LoadBalancer","arn":"arn:aws:elasticloadbalancing:us-west-2:019453415603:loadbalancer/app/k8s-echoserv-echoserv-d4d6bd65d0/4b4ebe8d6e1ef0c1"} + {"level":"info","ts":1602803967.5863476,"logger":"controllers.ingress","msg":"creating listener","stackID":"echoserver/echoserver","resourceID":"80"} + {"level":"info","ts":1602803967.6436293,"logger":"controllers.ingress","msg":"created listener","stackID":"echoserver/echoserver","resourceID":"80","arn":"arn:aws:elasticloadbalancing:us-west-2:019453415603:listener/app/k8s-echoserv-echoserv-d4d6bd65d0/4b4ebe8d6e1ef0c1/6e13477f9d840da0"} + {"level":"info","ts":1602803967.6528971,"logger":"controllers.ingress","msg":"creating listener rule","stackID":"echoserver/echoserver","resourceID":"80:1"} + {"level":"info","ts":1602803967.7160048,"logger":"controllers.ingress","msg":"created listener rule","stackID":"echoserver/echoserver","resourceID":"80:1","arn":"arn:aws:elasticloadbalancing:us-west-2:019453415603:listener-rule/app/k8s-echoserv-echoserv-d4d6bd65d0/4b4ebe8d6e1ef0c1/6e13477f9d840da0/23ef859380e792e8"} + {"level":"info","ts":1602803967.8484688,"logger":"controllers.ingress","msg":"successfully deployed model","ingressGroup":"echoserver/echoserver"} + ``` + +1. Check the events of the ingress to see what has occur. + + ```bash + kubectl describe ing -n echoserver echoserver + ``` + + You should see similar to the following. + + ```console + Name: echoserver + Namespace: echoserver + Address: joshcalico-echoserver-echo-2ad7-1490890749.us-east-2.elb.amazonaws.com + Default backend: default-http-backend:80 (10.2.1.28:8080) + Rules: + Host Path Backends + ---- ---- -------- + echoserver.joshrosso.com + / echoserver:80 () + Annotations: + Events: + FirstSeen LastSeen Count From SubObjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 3m 3m 1 ingress-controller Normal CREATE Ingress echoserver/echoserver + 3m 32s 3 ingress-controller Normal UPDATE Ingress echoserver/echoserver + ``` + + The address seen above is the ALB's DNS record. This will be referenced via records created by external-dns. + + +## Setup external-DNS to manage DNS automatically + +1. Ensure your nodes (on which External DNS runs) have the correct IAM permission required for external-dns. See https://github.com/kubernetes-incubator/external-dns/blob/master/docs/tutorials/aws.md#iam-permissions. + +1. Download external-dns to manage Route 53. + + ```bash + wget https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.0.0/docs/examples/external-dns.yaml + ``` + +1. Edit the `--domain-filter` flag to include your hosted zone(s) + + The following example is for a hosted zone test-dns.com + + ```yaml + args: + - --source=service + - --source=ingress + - --domain-filter=test-dns.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones + - --provider=aws + - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization + ``` + +1. Deploy external-dns + + ```bash + kubectl apply -f external-dns.yaml + ``` + +1. Verify the DNS has propagated + + ```bash + dig echoserver.josh-test-dns.com + ``` + + ```console + ;; QUESTION SECTION: + ;echoserver.josh-test-dns.com. IN A + + ;; ANSWER SECTION: + echoserver.josh-test-dns.com. 60 IN A 13.59.147.105 + echoserver.josh-test-dns.com. 60 IN A 18.221.65.39 + echoserver.josh-test-dns.com. 60 IN A 52.15.186.25 + ``` + +1. Once it has, you can make a call to echoserver and it should return a response payload. + + ```bash + curl echoserver.josh-test-dns.com + ``` + + ```console + CLIENT VALUES: + client_address=10.0.50.185 + command=GET + real path=/ + query=nil + request_version=1.1 + request_uri=http://echoserver.josh-test-dns.com:8080/ + + SERVER VALUES: + server_version=nginx: 1.10.0 - lua: 10001 + + HEADERS RECEIVED: + accept=*/* + host=echoserver.josh-test-dns.com + user-agent=curl/7.54.0 + x-amzn-trace-id=Root=1-59c08da5-113347df69640735312371bd + x-forwarded-for=67.173.237.250 + x-forwarded-port=80 + x-forwarded-proto=http + BODY: + ``` + +## Kube2iam setup +follow below steps if you want to use kube2iam to provide the AWS credentials + +1. configure the proper policy + The policy to be used can be fetched from https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.0.0/docs/install/iam_policy.json + +1. configure the proper role and create the trust relationship + You have to find which role is associated with your K8S nodes. Once you found take note of the full arn: + + ``` + arn:aws:iam::XXXXXXXXXXXX:role/k8scluster-node + ``` + +1. create the role, called k8s-lb-controller, attach the above policy and add a Trust Relationship like: + + ``` + { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + }, + "Action": "sts:AssumeRole" + }, + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::XXXXXXXXXXXX:role/k8scluster-node" + }, + "Action": "sts:AssumeRole" + } + ] + } + ``` + + The new role will have a similar arn: + + ``` + arn:aws:iam:::XXXXXXXXXXXX:role/k8s-lb-controller + ``` + +1. update the alb-load-balancer-controller deployment + + Add the annotations in the template's metadata point + + ```yaml + spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: controller + app.kubernetes.io/name: aws-load-balancer-controller + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + annotations: + iam.amazonaws.com/role: arn:aws:iam:::XXXXXXXXXXXX:role/k8s-lb-controller + ```