From e92216eced38e7bcbfd36f2542870edcfac39cb0 Mon Sep 17 00:00:00 2001 From: Akash A Date: Mon, 9 Nov 2015 13:40:14 +0000 Subject: [PATCH] initial commit --- .gitignore | 3 ++ README.md | 89 ++++++++++++++++++++++++++++++++++++++ cf-notify.json | 102 ++++++++++++++++++++++++++++++++++++++++++++ deploy.sh | 41 ++++++++++++++++++ example.jpeg | Bin 0 -> 81431 bytes lambda_notify.py | 109 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 344 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 cf-notify.json create mode 100755 deploy.sh create mode 100644 example.jpeg create mode 100644 lambda_notify.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f389d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +slack.py +cf-notify.zip diff --git a/README.md b/README.md new file mode 100644 index 0000000..58f41db --- /dev/null +++ b/README.md @@ -0,0 +1,89 @@ +# CF Notify + +## What? +An AWS Lambda function that will post Cloud Formation status updates to a Slack channel via a Slack Web Hook. + + +## Why? +To give visibility of Cloud Formation changes to the whole team in a quick and simple manner. For example: + +![example Slack messages](./example.jpeg) + + +## How? +CF Notify has a stack of AWS resources consisting of: + - An SNS Topic + - A Lambda function, which uses the SNS Topic as an event source + - An IAM Role to execute the Lambda function + +We add the SNS Topic of CF Notify to the notification ARNs of the Stack we want to monitor. +Search for `NotificationARNs.member.N` [here](http://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_UpdateStack.html) +for more information on notification ARNs. + + +## Setup + +To setup CF Notify, we need to do the following. + +### Prerequisites + +CF Notify has two prerequisites: a S3 Bucket and a Slack incoming webhook. + +#### S3 Bucket +You can use a pre-existing bucket in your account, however, to maintain isolation, it's generally best to create a bucket: + +```sh +BUCKET="cf-notify-`pwgen -1 --no-capitalize 20`" +aws s3 mb "s3://$BUCKET" +``` + +#### Slack incoming webhook +You can create an incoming webhook [here](https://my.slack.com/services/new/incoming-webhook/). + + +### Deploy Lambda + +This is done using the script [deploy.sh](./deploy.sh). + +```sh +./deploy.sh $ENV $BUCKET $WEBHOOK [$CHANNEL] +``` + +Where: + - ENV is the environment of the Stack we are monitoring, e.g. DEV, TEST, PROD. It will be used in the naming of the Lambda artifact file stored in S3. + - BUCKET is the S3 bucket to store the Lambda artifact. + - WEBHOOK is the Web Hook URL of an Incoming Web Hook (see https://api.slack.com/incoming-webhooks). + - CHANNEL is optional and is the Slack channel or user to send messages to. Defaults to the channel chosen when the webhook was created. + +If you don't want to send messages to the channel of the webhook, set `$CHANNEL` as another channel or user. For example `#general` or `@foo`. +This is useful if you want to setup CF Notify for your own DEV stack. In this case, you'd want to set `$ENV` as your AWS IAM name: + +```sh +ENV="DEV-`aws iam get-user | jq '.User.UserName' | tr -d '"'`" +``` + +`deploy.sh` will create a zip file and upload it to `s3://$BUCKET/cf-notify-$ENV.zip`. + + +### Create CF Notify Stack + +Create a Stack using the [template](./cf-notify.json). + +```sh +aws cloudformation create-stack --template-body file://cf-notify.json \ + --stack-name cf-notify-$ENV \ + --capabilities CAPABILITY_IAM \ + --parameters ParameterKey=Bucket,ParameterValue=$BUCKET ParameterKey=Environment,ParameterValue=$ENV +``` + +## Usage + +Once setup is complete, all you need to do now is set the notification ARN when you update your Cloud Formation stack: + +```sh +SNS_ARN=`aws cloudformation describe-stacks --stack-name cf-notify-$ENV | jq ".Stacks[].Outputs[].OutputValue" | tr -d '"'` + +aws cloudformation [create-stack|update-stack|delete-stack] --notification-arns $SNS_ARN +``` + +You should now see messages in Slack! diff --git a/cf-notify.json b/cf-notify.json new file mode 100644 index 0000000..7137101 --- /dev/null +++ b/cf-notify.json @@ -0,0 +1,102 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "cf notify stack", + "Parameters": { + "Bucket": { + "Description": "S3 bucket to locate lambda function (cf-notify-$ENVIRONMENT.zip)", + "Type": "String" + }, + "Environment": { + "Description": "Environment name", + "Type": "String" + } + }, + "Resources": { + "CFNotifyRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": [ "lambda.amazonaws.com" ] + }, + "Action": [ "sts:AssumeRole" ] + } + ] + }, + "Path": "/", + "Policies": [ + { + "PolicyName": "CFNotifyPolicy", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Resource": "arn:aws:logs:*:*:*" + }, + { + "Effect": "Allow", + "Action": [ + "cloudformation:DescribeStackResources" + ], + "Resource": "arn:aws:cloudformation:*:*:*/*/*" + } + ] + } + } + ] + } + }, + "CFNotifyTopic": { + "Type": "AWS::SNS::Topic", + "Properties": { + "Subscription": [ + { + "Endpoint": { "Fn::GetAtt": [ "CFNotifyFunction", "Arn" ] }, + "Protocol": "lambda" + } + ] + } + }, + "CFNotifyFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Description" : "Lambda function to post CF updates to Slack", + "Handler": "lambda_notify.lambda_handler", + "Role": { + "Fn::GetAtt": [ "CFNotifyRole", "Arn" ] + }, + "Code": { + "S3Bucket": { "Ref": "Bucket" }, + "S3Key": { "Fn::Join": [ "", [ "cf-notify-", { "Ref": "Environment" }, ".zip" ] ] } + }, + "Runtime": "python2.7", + "Timeout": "30" + } + }, + "CFNotifyInvokePermission": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "FunctionName" : { "Ref" : "CFNotifyFunction" }, + "Action": "lambda:InvokeFunction", + "Principal": "sns.amazonaws.com", + "SourceArn": { "Ref": "CFNotifyTopic" } + } + } + }, + "Outputs": { + "CFNotifyEventSource": { + "Description": "ARN of CF SNS Topic", + "Value": { "Ref": "CFNotifyTopic" } + } + } +} diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..e0509da --- /dev/null +++ b/deploy.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +if [ $# -lt 1 ] +then + echo "usage: deploy.sh [CHANNEL]" + exit 1 +fi + +ENV=$1 +BUCKET=$2 +WEBHOOK=$3 +CHANNEL=$4 + +if [ -z $ENV ]; +then + echo "Please specify an environment."; + exit 1 +fi + +if [ -z $BUCKET ]; +then + echo "Please specify a destination bucket"; + exit 1 +fi + +if [ -z $WEBHOOK ]; +then + echo "Please specify a Slack WebHook"; + exit 1 +fi + +cat > slack.py <x;yqUdO0SF!_sVV^w2mrhS|A3oS zAXL%M!4?42)qy(z0AK*95F!8yA_({gK&SxJKNtWWK&bzPwILjT^Pm7glmh_!o5v75 z-xg5vZR@|!DDP4J;eax{hyH_6Zd(C22Y{%iy{nh2r@gBi!#!SpKvZ5;9rouM@E2yi z>p_p&>k@CSeYxwt76%@=gwKbGfA1eMa3SZE|&Fv`)0RT9=czI|m z%QNU37&4$Q16TkGKmrg0f)-YuZgQHM4{t^ObH2s@F6YyKbO$DQZe{(O{@+4`);6A2 zpz)d@x23hGl{1KI002g1<>ui90I1(UI0x2nBT?P!3D(cK`d=$Z($AM6%cbfJG+7y z9|y!7mj6YL-G9Lr7MA~#X<=daFZ`D+U`z1E_Z>Xlo?7_-`SJf|<^0qe^w*!l1lBnA z9xB@4nFRD(v6HLXEe3UmG`m zczA2y>dXStPi;MvZfyj4pcKxYAo?R8%4=ou=Ux;bUDnI~i3&&u+d}niJoRt&`J;oi z&3#1>gE~O1ZCrHz)(r~wF8N!Tw{0Wcp8o0UAU`zQ=Be^69rQEwlc&$)f7*_Fc|5tL zgFb|=Ia)lp?OUM!&~rC0&0GI~x`E^IA)o-<2N(cv@UR420Y|`LWWRnN{PourCBOpk z0PFx8fah<@KP~kBTyX*G$G|h-0B`|$Jpa{B{?An#zz3vX{fqinTOPpn&sCp4Eu4TY z@D9!}Dws4(0`?HBWx+!LCJGb#ryT?SKYF4mqTNSRK~qBG{D%Tqfm%NW4-dfMe?n6O zui1dsd4RRcKQ{bZ9_kkA80s486zU4i(9c?i*l7(mP+ zb`TecHzW}991;gfhGar=AtjJ1NF$^j(hnJfe21(;b|A-)-zZQN92621S`;=EJ`_vSwY!DIfDXFY$zF&5y}G=0PiZ97B`l3dnrlEd7twrqy$Id3|IT{)o85%p92skzk z&>YbM(BjeFp;e-_p^c%fqn)9nqf?@Dp-Z7_pj)7Op+}-;pqHVyqK~6*q9ZY|G3YS_ zFqAM1FJz-+=C#oWZaz#_zA$CAQ& zg5`)6hV=%k0;?Nq0qX=C8=DDR3|kA^0Xr1?4fZGOKI~QOUpPcKcW@MNjB&hi5^;)f z+Hk((oZ#Z(vf;|&8sd84CgPUhcH%DKBJqgvc=1&6tnotdvheEg#_w{qE4c9Vkj{)u>!Fb@pIw=;%?$i5;PKa5>*mMk~orbk`WR(DG{k4sV=D>X%^{M z(iJi&85@}@*;BHYWYuKTWWUL2$>qpx$YaPW$j8ZlQczRKQrJ+$QdCk*QT(Q4pj4!E zqD-Q!r(C3hQQe`^qVlE6rs}5JrzWA6pthoprLLx)qd}p$L!(U-K$A~1L~}+y~NxM%+Mkh<>NcWnqg>HwQm|mLRf&MjpEB!75DT5rtQ-(JTT?}wW8b%dHZ^m54 z5ylH9b|xLBaHdM8MP@8!QD$4_*UTNva29$Nb(TPuQkFSZOjc1=d)9Q;Ue=#%>}+~$ zQEc^WKiDbQRoS1hm$EN#;Bv@txO3!jOmd=eigG$}zT^CM2jz~?9s4_3cSgBTxP-YJ zxZZJ%aiemJal3HmanJDJ@W}D_@Rahb@{;jBmhkH-yUdX+Mdk8@;K^wtr!C4_A zkX)BylCqG>m0FQzkT#coFTEneC}Sa$C$lEYENdSsM-+(^brdrdmz0>4?37BC;L1YE0m^MEs48kINh&j{w5nFBC93cT zA`gNdbgAK}Jyy$9TYGrtp~u4}brkgn>M80Ak60hMJgV0KG*mTGG!`}4HQhD8XrXCo zYGr9{Y2Vcj)b4#u{MhXA$H(VSp|0Tv!!sjAqg10!V6<7pFi6F-xFQ!3M^reDqQ%`D75o1>cRnSV6D zw9v4~vpBO8LAvw9EKI<6gC{rAD$e3`dsgM(+k=cp)b}Wlp{(b z@ghAUXQCvca-w0;4$&hq_hK?)u4AoZ2jckS(&8@Tt>Om~?k2oRxJk549C<1HGW!+U zE0r$%M(zlGjtzQ|ewbypDZ+nrfEXpC*`=la7_{oxbws;hTmGmW)>!mznmN zQ(5v^m2YX@#=QOc&idVWwrqAq4sA|c&hPgQ?`LzBbL;Zh^3w9r@_q8R3Umv43q=b{ zK2Uv#`*2m{QnXU6UEEb7Qd07f=Hts!lv3}~oigLHZ{_#P8!C7zax2Ly<30hOyg%($ znO99$t5tV=7X4gN!&>vUmbf;y4pQe|2d}rUUuiIC7;Ajc*wG}>RQrYZOHngpbJkbV zuPrv|I?3L?n?UU+j?icTG z91tC-9~2&}8xk6-9Tpm{9T6U>8xTJKuJVb~pFj_Ad4#4+sz59&#Mk9LXLH!S&&r2oJ=~ zar_D8Nztj`X~&u7+0wc5`NhvzBqg%=m*}tF-+I5dFMKc2FW+2oUNv2-T`$}?-`u!a zcv$?21)yM!Vhd);$3*~uYXHU$-v9s$@2~vp567Qu`ELY<8-LJW=l_EL%F+H@69#}H zSpd)p1%QWb0FVtHtRTh#&$r?C6IlS|-o1YvAmz4r+TIiR10XmaU}%E8xjCT)0Q4pR zxbnEUxp;STb5#Jw?cV{Q&Hb;u@0J^l007>Dxc~qR&4BPf%1s+Uh=BrwGC;w+AB7MC zC4}5`0ra5ms9<0MmVfvmC{P$G8af6h7Br4haIU1295VBF4LN zXvA6;=uGY;0%1wH7|ilj?WEdcaF%!#l#ivD=I0g zs6Kf7L`PQ-49TplZEWrA9UMKqynTHA{GUC45fK>`9TS_J@;Wsw{Y^$@UVcI0hoa(= zkJX=RYU}D78k;&gySjUN`}zmQCnl$+XJ)_8t*)(aY;JA;*x5xKpPZhZ|3v=!eQOs4 zfc|CHzbyL?y9hzMP+%}94E@$F2#POwKnY=}jCaw9R=ML~h0LZMJpG*qylVSv#V z8X5)`#-D=qcft8n@NNtKzse0L1Om!{!C>g%KLTt_Y=Zyoa-; zEWB6ZIA>Xyv^k_rmdtu+phDRj==tPFpYe}VDo63Yuy2vNK)5)86I0X^kAYV`<9%+? z*u+18{`Z(%DgqnCdd9F!w#c)A5>z-I3GNvZRVGKv|9TzoUafu^`VhBcFy2S9YGk~+svZ5 z%p+Eq5~h|LNo(f3&%v)9ef&zUwHp8=$^v(>iaOgq?^hfuom0eu4@xiP z2vC6TWGZH{w&q9$21`pyGO?FN%y9+>Sw@!qT^deuzAEV9yc(zR?g zhA9!d_(N)aKVy>gC_|#+iZi>rgvLWWd+2vAdcD@hiJA=8@?3I!BA2=0Pv$tu8d6e` z>cCT7nz;hFW7@ebPP?Fh>XyqO*+be~bW?n@fp?(`6}H>@U+bF^bZ1pbiua>2PohB`3oX=g#fvfEm}gqTY>u9aWv-T+RK z*u^^Lo_A_H8jsuMbM>w9lj2C(KjW=ua-%!xXR?+3ZWbY~VIxhny$?I?1MYPBEa18C zD2C2g5+N$PxhnCUUOBiKs1eN%QLPqe#k}vmtQI>AxUkHOt_X0pvCqt%_G%Ei=gjlI z!K6bh)BxC5ft~G2l?dL`jg=+QgeU_4f3MJQzFjpU&Ktcyykmb*_j)eDbfx2@q&-0g zdsV|W(479^dgjih!s;S>x43bW^k@8cuDtlLQm&GLCV`bw&JDux+Css1b8HT^xjj2e zq}AhH=~T`W-!s%y8D4PW9rW8RCJ$*mUivJvYT)E!{UKp(zR!~0o0lne9XjDdkkeCt z9&=UMHmuyYV;iM8by{-z^+~ikSaki{(pT zq)1J8=8U{7@l^Wx@Y()Y(W;cK6Yf(ak$>=HU77<=b88P%eDt|WK=um}%59;qtFAEn zU_ue1oeqPFO5tBWMTjVEQ(PBOUn)|H>HwYwI`~D9IhD3>6o?S;12k zim?kd3LXl<;PLwUST5>OGu5MVo|<7xZ;9#8VdXB@^Axr9_bAF|4xjyk z5lFd?PlH_I;v=1Pm?pa>n|%AVX;84$B|za-I=dr9SPCSKH&AS8Rb=WMG??}g#vR_|+t~-;i z2D_(*nrCuXCEEcdiAaJIYeZT88H)TQj_uVOX}r3mtBk7*uX_5qS@-qhaYM0ACy~!r^^6>(=LmTZE1$00D(RfmAUGRgNf8)~o(*vK zb}>rcw)K5!Adq`p$Q5l*obJ_}$!KVKQT4d`yUFt%+VYVJZlVGgGQY)ClQi>{2K=9) zLiwv2F?HE@5fRfd1?>zItK$bk6x-RD=tp23>|kBhf7b?g13tFgl=;2aumsn6_xDE-~t zlPB3APIY*BE-%5>FCKy&Nyz`o+Pr88Z^`}>_4GACO>KZbPk4_rlRXnuRDU77llJ%t zO}5jUoOQi0hD;-OcTd5puagg|42)H5lDlI~Sd27(C1Aq($VF+!%%ymbd$=yxs~WkP zlYHuW?x-9Jh_zSTzf^`dG>;$X`kPAGSPIv3x!$dPJrb$%TBCk&kqJe|Go@`;mh}zo zy&vbt8m=DWYFkE(_oc1yD9pDfv&E!SH(ThDtsjuFgNoCkRJu9E(s|W!KZ+vN)9&n> z3iOrM+#&Or1p@QAaV7YrkHhn&ywkPHE4%)!^hRc#u3}^aH{SYRbx^Inl~_* z->DLvn+3*ZuIc>(x@N|AshU&;D>1^{8MP>2@A}Y{wo8UBW&MuIm2$pG6M@mS^dput@xCMnY$tD&SVqD zuDD7z4UJfHi;14BaUGvPL4Tk;ed9P~VIOY66D`^i{y zoVRI6D!)7CLJ9N0U=}0M$JeS9ya6I=S2Fmx%X#=%zL?0BYg3jVY-K`OcQJX!3U%(3 zvsjD5;yGdK%&eiOO>2P?2<(m}&aW3}2|hMSYfjN>NZ`_Zgo3tQ_=F2J&9l^gp3xo$B3F_n9R1kN| z5MHvc%tt%d&KD)BmVfwqwIDD=HvT=y_T7+UyVc7f?IAZntk7Jd=|r@J$4|h|I+-gb ze$butqfwSa+M0u1{2+NMq2@@nQrYf+@PRH%LJ?luGaJ9C1ZfeZt33SOdHs78Z?)N) z??M=PD(qhOb?qk?UTa%CW~vTEis`OzJ|%o-sNE+`h64cnteln)Q) zbrPv8Iew%eg{4^>TLDB1THs)8q}Aw^CL6C2Lf}s4QXBN~3^`MtP$~Efq^%Nq4B6P} z$R(=8U?!fBRe2dU$E8e#c;@NS3FsGjnt^At5 zH?`L|4-ao)(!fJofjJXw17QoFCQNBra_-TNaE?!OMW*fn2(^wT=bC%FJl>ASy@Fem z&g=$j;R|8h<4TV`?ngu#$9wiT=;JF_3LRGIdQ2GFhzP(3n&rAY$*6HJ}+2MFO72lD`9qryG((OWAV&e{|@#i;yed3&L zy4wjOzhLZ$w7E_g?z?t1$f=26VNsX5?YKJL-jjy$T4#3s$*hL~!@SD&2b+GQNzI@6 zCAQ2sR^TJqAL1Yf-rLv2i26&Gxx^-6MZ9+wA#6D|>>24z0Xog&#n^>+4cEC7|++{YDQ)T0Y+x#T~09r z;r_RimK(q6f>zC&%R#hF!e&t`ZZ%^@ooUZ5$987sygy_V=Y~-pTGVhumA=!dHHjsRP&l`1mfbTs zdKt`$R9merPwkE6Wg~L*q~PHx=dt_R)R6S#3r6`tvZ|RS%82~x6CxGTDW3pkvKs)^ zqM?DTK6A3#K55Z0UF$oBmVStnBKKovjpXjfBR($y!ZyoU(j6-Dgur`ia^`|r?JSw8 zZzdUH##S@R)nF$$+IN~lhafl*^l*+Z&`h{%=Yd-1vq7iKy02_i?pGO3g?Y8jZcN?w z$Kw4j`UPY%PTn4fqU!jQ?tJ;0Ko0HaktW>nF$JpO_sJ8JcaCu2%iLOJ9cyzd#@)=k z!gVarJAM{#&xXByTO{F2IqUDZR);4Kn+|KO{EO#0m@O-v&EdTg{r|34=#^JiC zsASt#&C5t0n>D{ctK!|tfR8~H0gVG)Rf^1Nj%m@+8J00L_87n3q_L!!mNsa)NoIGh zDwZblp|Ek*IP{?SJf~2~^e*8#7DcOQMHiGFT zmV7_s6Q7O}?lz)*92ipF*EhiVqti7*+V%NxO?S-nBBK^whRhsFb-2fg%0s-@ z7j@TxX{M&y=2+`Gx(9=<&aC-IF$H$7)Je))y|U^9+apl}dXB6V+Yl%4L^MSBrJS>B zR1B#z^MzqMRazt|mn6>D)weXSM+XMVinvU}@{sxJGnHov;@!MtCU`##7AVUL!>AO9 z)ZUmX>SPG_p&KLlUhmMFwh8_b9 zy*_jK@Z3kLr?^W!abc?maI=B2Q)dx%1nO|X99yDb^wtyOeu^|qgSVWIqX?dQ>l&BR z2)renzr2r3TIGw#rnv!Ll!9Lf3>~(%riTqVSR0cn_-ynU5-cN3zGo}zP(1F>*A&yh zy`-yw9~R-2kQIy|TFMy{81>gi$}H@#AS~Rrgf-SFDGe#Za_9$y@H8`gzpSp5J$xJd z=gzp-m9G8{o(=(a_Ru7WISnd}&HA(pV@BOO?WznDzR=KdX%fHsPHDD@bTv7Drw_`7 z2JP-13;|YlHux!$l@y$UzAoiVC9(t3rm_oMEmc?Vuc=Mta5qjIscg!-HxpiX?uwfn zyx{XJkx6%q{mI``G!)3eutr+_gs3M=>MH=<%h;hbu-c*a|neUD|n=lPpeHUg5?x&SR9d=it^5 zlt;Kp9@2;VX#V*9A?d2}u8D?n!`S!BngQ0XlMx$euFXAC01+y+H_PWu!TkX9dEl>} zvFz8zc;sCnxCfUCTxzVBbr&@f2gDe$!D>fb0wct;>{6v=;8Td~9oOgsyJ@Qd zlBZ~QF8*1k8Cr9#6L~#3S-(5V*Vn{GIRb3V&jx9RlNw0DWvrRvkPZc_9rjJdwqtdx zm8@M|@ra1D#;bI?`a-tUVxHR9Dv3#w70I$0^Vs-elkxlviSZ(O0l7I5XfnQ2gNJvs838<4pN6zTOe=8m&e2w^ec^+f;LD2%6Dc3s< z`_18cBWoDWn*DQ9X55tQ+I_MaOmA1(A&c+_ANLv`yyfrflYG95|9}_$l~V{-#id;F zoYU`$A_w161y`ZBFQv0+rbk`xm4)e|dsdC5Z#r*_F+Rt!`tHHeKa|f7#YmEuA=SDJXZ^hi zvjPSs?$@P_*mQPEIu75dNqSJqL`KmEgmX=tD7LLO%fNqj&Y?vVIB>brPK_i$VySoX zl$wa7AAUyXI__sqK2#Fun$ak75;v`InR(c#mSQC_H~MLNFqzXtGeCmzk90oM#pFy6elb{ZXyIU}y*UY<-TdpB3$0 zlg=EHK>9*DB)o3`smEvK!%hYhmooXwPIEPp)I7qNE_OkMb=_F$J{{qYNQlGw^V%%H zPAK8~hr4WkG}aXJ)ARP94^L$%tO>6rN5S{YF%`ZT=AsU&@nx*P=C4HjtQcEv>2(>I- z>wbz@g4({kkv&g5RPha6<%b_9-xo1AlJo&3G|ypAT!e2M_WFUws^8>KWRA)Nv0g*9 zexV(i%TR7=_<_&B303k6DXXjv%V+3#>2@Xl^#u5tNm9K;qhQCwanI8}QmwGz+nI!g zJq&G|oJXh$12ftMn^W5ZfW6}QL@z&+5-5V4Sjmaqqglc;Q9szON&L-ucv`xLVH5t8 z#D23WQqWQk-JZ3op8|}3hy7dQq`8sA?ILrD@7C01=SBT zE0diS==}tyTPl^3^rX!Y*2?Ec2j0;x<&psc?Rgq#HnC?*b86kQKd?g0W0qOMdc;@2 zLN70Ni?tOM8oD+pptKA<7Esv6xc^^o{3!w z{?>|7E=g&z-gIN@!S@w9Aw4s*M?u{pFMbDB$ZtisSQ-gWCf^HLVI8}%b>$brrV zl}vBWi{GQqYb$9hqnSR9O9~oz+fEXxQPylfA$s~HeA6n8jALM+BDDGw*DFOb=*(UR znC;FfteRYht>F`^dlx&T(NTO#dD7ynrrJ93{i!8twwGElvjYKSq)nri47#}2@&2kH zm|!p$nPQfspEf{`v9qo_x%#ELskZ64hK;RJ&gWsG2MB&8tRH2V+K@h`ILKk`D&qRv zGHzm2&>D5o<#v(G1^7_A$MYSU)FAB(%r(RbF(ZAjBKQE9|1YfacTrSV*NK7@ZgtXvDIL=Vc|I$lh*jMJ@8eP`8pY;&CJ&*c0i$&lw)`>N+p z)Y{F|4fjC@K~Lp7+|hmQ&zXa!VZ^CYFBKlG1Y0;<;~;l@UDvo4**lwhBJ!OKeIs~X zy`o*%B6S0tAL&gWFlKJ88CW+t3F~jX^_O3j|Me7qsI_>R??GT&uxFqy(guOv)wCUX zW)}VoEr0cb8XpIlJvNRgsB7?QYM$71!uW7!kCg18+lBeru1KjMZXudQ)T1@;aM4Xl=$SdMSs+4ittl zkk~LrY09Bz>X`>S&t0-3Z-Am7nL4B4XyqULvL3_r;!iKWln(CD@RppHYUNTk_a@zs z!5Uylu_Dp-rSrey8n0CsF`jVtPN3V8n5Ujiwr7uc-pj3x+xMe0ybMo{R#DnqMrsqz zm!Q`fCzY7B=JXP8u=EE{xjiRjV#7%-MC5?)sq_@f$!C>swLgenWQ+DC7=MnsBA=7u z^o0ESxnc$ll!G7UuR4{pcg*$V6d59Cx|?37X)iikSom7`p5Jp@^Tnm9uEt1>`}MT{ zxa48c4>lnG4gPa!H00y8g=}^NF8p&V95wRG>H*dLMEi}V#0kCFt&OGLy7M*LYzIgR)3fviD8oiBIvPgi5Sh z-?n6szn!6%|S^X%x~1c)YcxCjgNRk&KRk41IWU0!Cgc!gkHF$XE74NYhHsu z%UIp1DJPS`zse@|_bfCv8s;+LO7Y6W%(|Pwl0K};{0sBfgZkwFMVhw2pbHg0>a|BD zD~e9oag`L!bX@SBQoI~zCz!yz!OmO_xt;`ujX-J)=C2XI^%OG;?FRa{W^|Y6h5V;T`EbkR{TJ@)dcbBp96^(2CdUL0u{5mN`#%R8>mXDVRlKMK9)A#0LpG0 z4fG5T*Y>j1Tv^Kxj##S3Yog-`jd0SG3@WJB_C=OZ%$u#C z`%To)SCc%ol&fK;Z2ru=Web6`4CrkuE_;cKT$SByZ6~Aq2MX6g%g2@SZ3XDrH-McZ z{mJ1Ckot@k@ZUc7$-M!jkACUpu7CX>ewu6k54?2uWWka1t~g}$%eBrAFUTrAouCG} zlg#JVmxA=LUe6l}gU=VdD}6t_p{KUbra&wu zUC7H-80jzWQRx;}@tkJHKb9BtihJ|~U86}g{$4vvAL)T9J^zDawJi%Bjqenc!{Aty zxm1A9tob8y;sc$EzVDWouy=*v8`~c%du@_;f(A`6O~$*`WNX$xHSr&KLbe&o^J(S> zE|zStFPLE91hYHQag3doKNvKqo+_GdR%+p%+WHbwWoA#Fw8Z*acfYdc)wrP`Msy_* z({8SMBBKBopV)?;n2xs5*U){jvf_(A@K&)yJd;~FuoP^*Tb`I+STEk>?}3(Zgfe=f z6gZ@g=l&___v0|NH~2}xqJEw|$$?7nkmx}24-0$4=FZN`53@NVvo=(Hvb~3VUyag# zcUg(!Ytr9TwKC%Xj6eO}2F?oJ(8KhR5>MbR5eRyfDr89U(!y>qw?K2YO?!CIo#P!F zqc_blUFn!8X#(>lN`WL|+V_68pc{gdw!0tkYEc4rtwv;1Zx;N&^2-l8bz);flZPH+rG0 z75T*bxUyyH9FwQO;pJOv1FaR*2VJsCvu#*c*mF`G+t3aA=h--jucICK)Sv{k%qG7k zqjxgulPr;IBkD?&`>Ci?-S4_)z%^86K@ZD^5BhAeaywpDe!Am=-j+$0f{^L0&q28q zDf1)Nf_LR$AI{wX#$UcBFP05{-w`pib~jKZiT_C#n2w?{ZwVnvVe9R(JNo+Gr^rnj z6UlcW?e{+LE}X6&L9IF2T60NmRXkjXe5O*K8{6^wnDU@r1^%4n@Rd4?`{C=NBW!{p zlFFr1G03mdReX#~b%aQpMtBI+4sKfh-V`ZvO_=r7^+}6=>HApL?TVxj03yoQ%naDcTeCKped0*0STXqtM zaol~?{%FOo2lID!ig{qfg`ml@AN%Tc+$M0c0t>52-t;4)2&T2=ZB*CB%ep{ybM7uGxLgXxOt^C_u7@+io?W z0yBHB-Ayu9^O(WQO(!){4m})0N)CLnrL~BD-<2V9k)~0Ak7^o~Ca`zw*8A!;1sE;9 z6JIb`tej&>cvB)j#N30=i^q>i|6pg1Eup|wTqm9^*jB{BzTxiIWxRoh?FF zZ=1CWkU6W9*VxmwYUR2|J(=mz&2npOiDTQ5MhRGl9h~uKLSdF#=K)>`Rx%9zgD##w zYssM}c5P<(!K{~}&B!1GwHDkbx71OZAf;s~7OW0(8bJcPCd~M%|j4VGYsJuw;4S?RlGrX#i5KK3@FN9CI zyTlDA_ypf7?%^16kMmU(bl_P(UQM*{*s{s7KS}Kn8v^Qg-jPGsBo27M{RNTRvIvo= z7KS~gksILA7uCi0wUhhoQHRC`syMIG^bI_AMed<7l$LOrIj?99p>Lg+u737!G9nY zx_(UuX4ekjYm+^yb=4{;>zb%?|HACRwQ75R+2uI>fKJ!{`@ z)jJa?m+NQsD9EhqSwc&?6{U{DVWGaI_O@gAp)4#LT{07xEi0!s9t%_~>MgY=KmVQj z`ulgOni4_v#0D=Gnjrg6R5clNHNbyVwMpepzu6;Czt`pvEYI&`1~m-TlM58^zn8=v z+2FWT2b`vDGs(YS=6#n$JS3C50a=g>0t<+`}CE2ZAU@mSYt8Nm0X$%zk}l-%hyi zv}1?%ic$h^z1P5@l-)$1Abm$osOR09+7W?)pD;c#hV^9m`^+tb*G`S!AtR>Sbk#6x zV~ed)2E)Lo<7#4-;D~}G6%nQONR>XZ4L3y*J_c!`I88)P6e8_JyS9ERD*PFrox z*5S;3r|^3lK=jCsU;N}i-rQei{|2xM_z;MT3@LKdt+erVdcRYp4vV(*D^T;&RZ?o# zE--)Iw_{pUt<*=WPs+^j{FQQr13ycJf1r9H_*meRPe=V(v&=Z5ci-sB5lZw@E_A+p zpbO0{PWH3b@mn-7OJxYhpO_A1tqAC9VIL3Ve81!ur|UzOrX@JKnQ*A{>_F3_clNOg zUSwkeS9g=?=VHfcGI{wX?mX<6?>_C@s5prHloJvhkyrefJsudSp*y>5*`&bdVswgr zsMyZ0^8#2c`keF0%e$Tpd`t9x@nL7owSb1shvwRP15*bb7>0FV((!xPA@irTQ0^J2 zBENKvDZ5&ADeG+P!Mg#Z1GyIx_q$N(>|{3x+BHPC-i7{fgm}7G6337aGE3CsHqf3- zkc4Kxv6lTZ2)wrwTPFd2$JoZS*|;g-wuOt)<5MIQdj5?S z&*kw@dY$VT=S|GZ$>aW>gH9LEc)KD~4wP=2?|b4lR|n@g4sO*84%OUx82ER;X9A&#`0qVeZ$SQL^xQ46oJ0t<{(g7#W4rSLHKr-j_2A~3dl)eK$ zK_)I=`?c;|3qr>9B*0LZw)GMbGI41S&8zUeCXxvGwE=b(kW$T{kIVfR%9$;CKkIS7y3gGD z>si})py~%F5ySF#`TQwLU&!>RXY5bnwT2_uk8rCinOl?{f#otI+K@++E=T*|-tmbd zBM1F>&ewVUwW=3g=#;$*y_(=&A|0@sT;_`<1=fxjxy|vr`R}y9$J~QK{ebGeCl}tda%W0?9UA4Vbn=6IFSIz-7+PPjn^5WLXGwwXaj$UQUBt z2fQcRmhGH;V3VPa-#o!|H`OH7`Lu4TL44#EkoQF2rB!FUP98(>7YWO?yWL+vY>jMN}+(LcH;YzzNhBn4Rq+0$f&i#MHa@A@${B&)0o z1kTIZ#voyDak3}Rpc_|@ByvcQOi~Knrd-qGxc5vZD!t3)B>XbOC2wVZWTiATB97T^?*cz| z32kz|$6bGy?&&ooV`bU`qr=FbXpy&Nhtlm^Q+4$Q-4oij&|jgKzY%1u2(#`MA_S8< zIK%Q?GS{Wkp-r3H#TrzOu})E6nD}Db8!XLXBpdLo#k>%}$$dre{4}eJj(hC#-m1hh zm1Csbhn@3sf6heVWDQO||9Ps-jH)r&eo4&&^j^c!#1=Mvzt3HCWHk*l#=~nz*y;r; z+}6qL@cl6Zo}H5}w!73S^-S)JL?!Hpk?}KQKSL-lS&P0esRg+f%lTUg#S`gEy$wI{ zDdJ0U)a6@KWf_RlenRTpMbw^uS^G-fJ#OYWXv5;sUfRED}r^TQ@1jYd)m76!-Gyg{uNHT5kQI%*Vm5;r^|5WXL6>0Vd;@ zDT7yA2RTA)=p}j?y$GlFe8tJLawY$o_Iy8(TD>g_R0YfN;p6;%iBcJD+Ad@bIY+U_4xrw-m zM@h>PoMA@HN`1opf!GrIdKkm8-iBEy0cvC0WHEZTlhaM-P>=ieZNeUp>KFb3rJmTjyH(ebD_p!V2ScbRqa( z4@QH=1&#-VBPz>6{@s2Hxx>?kK$sX@F2Bzx;s;n)J`83evrj{>_#na5FTf(Ar}Vw zlkdbiGa+RfVLJ0&7t0JzQv^7!(Q>YrufV0`U*I|)J-(zu`C(S)9E~AQ#>5M>&XHI~ z29pO|CC*v>+|j%i%DN1x)SpygGvDapufR+b45XF?jq!o;OY*fv;;wIgpH<=T+KKch z4QWzL5^uB)$`84<7YhNAS6{Z(kErefwClVEPV;B3)P7d-p~g-k{kDvm<5J8!zd+oF9YBK-q;dQC=6=4u%LSDdF=a1Je~Q6{y7^ zb6Hiz_8roW2*ckl+iN+Ud-#~ke(T!PE1$*$d%V6hG%dQG`@TG4DdEslrle=o>}7@~ zDbCWV$#e|vDS!F;{C-_ixGRbJN0Zsy7`$9-c(oEu-K1@zE-}UiqpGQ!iqI*Hj&YpV z+x8o{3;kJL)e=QVUGONE0P{A*=IeOxwbV8^J?bTUYdwNAvV6^%m)OqAsf1d>_RXU- z0psPXyg63WCpCB7D$tl&3hZ3XtiWxzF)QtBTC4O2DmOr_uJW^q-`|9#CQGFpZ26Y6?y`HUxUAmliFr`7G3a+hsyVinGaN$o7)Lnedi{8~*BWpk-p2@ZCy z{8P>@g&HiZi{(?5=`J?r4=0FLAI9!}d=Z!%x)2o17n_Zd^C;zUeRHOL?pvb=N#7SG z5fA#eIFeDL2f|)OY7anQ1pXu@VXOJ8A#vOAx`d+dKdKzeEWRC-xs*k8*{Afo2Dl1! zQRlJxEOrwofE~r6t)CRk)ZmT5R0#sh`r_kpMv+a5Y?RMmeriqk8l@Zl@k(Zps{t!2 zk}2+!%w!1(Gm3^ zK9VX8A`NI+QUgv|0jar?9L!CQqyl}=BTxXLe94d&OdF?mTv?_Vn)#$LI%|+iZO4Yn z??i-`hzR2Zt!Htwsz>EF3o`N>k+2Mn7yUXo7Eb-hyE7#WP3^^{y1VWnhXd>-B4eONSH4MpJs{G6|TmG}hOD`kJ9Zt^R&!1P4M$et%>^{3`AwY<_4xxi9~5?>#1zG9~C5`iHXEz!_NH%<}KQz1kz)MoeQ zIWB!)_;u6@u47)DtRM~Qr{#o*Wn-aBo~n-frEd5BZG1?*k0bNl`yuzkh=m&fjudn;`3H&d zkw5sqa~(PCA-Ozg3gtEtUJY!Gj)1e54SXA06pTA2Enw|nT+nZWHepH2fZHc@ABmVo z$G=u62HZ>hJ*lCVZU|!o(8vXNynGz`<9L-vF#SYOyyrsJVAI;hTic$kTG}$0;=cSl`0McGEq*X>6GCZz2}HnH9`0RInmk>ho%0>PO}C3>gP9u z%;bt=DZ=AcX)x-*_oo_)KEB&$Xa~Q$it{%ebiUbBNrc*GeCrG`SQ%3AQr?|<8fW2( zIpqDtlYg3y+Gfjz(k?5#p{6^$v2xNv7xp91VNYQsJvP9;zIw1u>-ASQ)EI(L8SJK* zE#l+rAfirOze4*!Mk51uKU@m3?hO#G)9Q!DEI+@yN; zd>eg_hF_KR-v87(izHM087fNxDCfh^BWyW!)iI zRBct&e;uosAo3hws5A3@jMwjb$zyGfq@kenb;}nmF~r}h0DPeZ@6d}^d7FN%d~#XG zVG0tu_9uM4CeCW7GPH196ZoESoBe|Qfzi&(A;XP`vi5BPlgmVW))=rg39RvhISMpqbIAm8iMRl zZftMx=^PuwLCLa_9cQ6Kg@pKPQH8$8v$w}JujXQ|54kYL1UGTTE!?UPRuZGDJ}*~$ zev&Izc0d(%T+nJ5D{DXpC)Zc`M~FRIilehs4%T7Ve0iU*JJ$;A%VR)n2h(34w|MY-Jy(8%-EZBM zpZn*Jn;v+@oTr7@L0-;;W1)dsPZe%GOtgWx__#3(0>BY}_(Goai+I`g!tTtDEXRs7 zPRs5F9a7{FY{>8S`F;5&ii>O*(3k6zqI+r=l3CJ5S~zF<`pK z#+6peMgs5X8`$|;$Eb!DfD-a%%Qq-g9K{!sL#@z~s?!FF)#SLD8Qk?H&&Y6|GgM~T zu@OmIs#!GV5!EfzYWq(~Lc z4plgxCc6vH1=&C70<(H^pd0s!6I&ZL71haZ;{m1aF!H@pRXyd}CV$5^x8I_SF|wP$->ho=Fm(_wj6BMPzqmco--pws^j8Teb0FC4dHNot zPn7NDw?9aP0#~@?D0`KOk%2-ju;D2GXVrKGE^akT_6x6Yo43bPuBkhg;(VRDKt&0i z_p3dJxB=|Iuoed-iQ)Vv6x{cAc10$Kq5(fXm#n^CpvuyJ{5=cZQzirFD%}qbl*gT7 z>`~A@#`FMC@a_Sz4wEQJ;-BL55askE9h;UQwwBjOE$z`ex9hSnlAHY|KLr3t@DjWT z5sEvzq^EG8BOrr;YYqdn9Sd`f(pSRcFIgiN4yIo{YrutfVZYuYz-p)r0A3TUmM+uZ z0=79okJBmT$_&thG9*%7`zS_#l)*ov^v0pPPptN<0s0n4Ol@7ZwCjn=ukRI9nb>F1 zEc&zv$vC6seg-!j$N$vUP{4_+s1SNZE;%8{-yr&291zq_TH!Y%6cfRYHvYAWqVbXY^ zU|xy3aF8J9GrJNq4-T1R=FBzG;TCYBeH(MS=H)K%3AjnY9?--D2%Ln^VBPM6a{+qh zH@$VEmGp!??D=$GQ$N>1jFe9DaCt=OSE;UPXUSxS? zK~9Ra51;A@8^?u{@0V!8ZFKm;zM)6A)|R*eS>21;d&Ui}#Npr0O~rQSb{V+=9S&4Q z2CB_-}k@@AlHD@n_!GAj>oSJ3;3EBgOS^%$dL4K>73Yzrcx= zEL^}2i11oH|8$glOJm-oCbrlb_{lc`zu>-d?wbTF%7kkG{;qLOh%}u=*sq|Mm&aI0 z7c}&8x4NaKA2cvBw|>))eHTNS4Hh59n10kgSku7BMkM^+mVqf^GwR;L!$6vO4$qS(yOvGuAaHz5L3txR z{DG+`JY|E$y`m~)L#8u6Cc7)K=LlHID18R%(c&T;fo${sj8*oFzk|Y08RyN?^-3}{ ze}06G%=GS0FmW=mlX}!k6#F8(cANY)^Sq~P#H|5%%Zn(EONV)QO&c>HYJk=6f<1!D z6V;n^+R~t9EURS0n2FP>d8r1ZbN90oaW?Noe&*-N&p6-9nQqWOj>%vuzqos^)!9+P z$M*+mcqS<$=?l7Hw}!*754tGhoyY)`0Q|1M9X&pvk{NEd5|CDu4kcZwMSWAxH+hpu z#M6cnb4A64k@-z55u^OXI6FiMpSSl?D(!}XntFk7jcUqHl4>T(7Dj(G4p(jTa_U3ZIGeVs%UqL{zl${a~m36jluIT+u zwPyG*ZY5JZoIA<(YU2&qkn4(oaSSqis6Aw2x6Vi#j6w1%^~3#=i;u%sTMY`3VU3> zk!SJFrRVc)$QH`1oeH+CO-s`sBu$*;p^8!Z z7rRY{{!){f7K-UUq;yeRS*A<4(R_Z{1@zF%nxOf&yI3Y<{xQSmmF4d zLyC_?)9ycfSyA{RAU4#}H0R9qiCI#<-xbdG+`=Lx;p)=3ZEFf291EHjm#+j-*51Do zUlb&A@j5Tg#b`-xE=O)4iEA}g6ge`!)c>t{UK$CY`_&1+LA}Og>J$guP<$eX55|Qx zZ1sH{E2`B!D*C)cBYBSPp-P$3c`rVH_bEflvrN49L4X{r%q)tR*6l3bIQ&7X8@DPm zTA6afD`m|+Twwc}W~pMwjMcX$lpg-hyk@Y!9VM~rp^P6_=p8(~xvIx(wd%VAJbzUBR;-oqVnR-#&};^fQGU}RvNy*Tf@s-b_ZuxhQ+&z<}A z`B+8dYEveGkDw|N)RTKfL7fDgClAYuyl3?F@U5JztyH=p7)EQPqy5P=$7P*1`eL6C z^O-zaCTmxm9Wr@HAtKoW0xI*QH8{uSB$E?Y7r0nA3P{JKW4)nx=5}|SGEwI~R+~BO z+>IQP5l1)sLKOkbZTI_Sg^b^D;F z_te!0S$dSCx^??3L!pKCq&uUliHoN7v{~a`Cbe@)wb5+_ERZw$niDiOWKR@hND#J* zK$uj@mpcHd`zxE--Q1hwnMn`(bVW_7!iQX8C;`PEB(G2LK>>H2Hd&XHfg}eR^u$eh zF+wiHhd#fV4QLyll3KR3=rgBlS^n7P6RV{`dx~^uJB?5A?V+YI6%rsc_yGv&abIS; z5d6|!T%kG~kqB-j&RvK}U@)QmfQ zUH(09D?iHYBelN_JpuoNf-nE_<#-MYysAW* zOb#cZuIQ_ZT~PwJB$+KHbLg7CyfXr+wauPo1T^ia<5XZ$ zr^vtTXG%``5MvhtZ;9{^fOexJbbA6h;E^!`F2v(dS^z0BKu#d8Lm>AUUoz~z@CT_q zR0xYAl@hgC{l}my`>)EWkH#onGnWDAd%aoXGIKTj+5E(B#5=?)-JCeA!mL_e7x?gU zh=%3b*I>i~iYJFFzvRlnRKHhP>H8;r89JI%N1EXh!^@7A8l^XJ_4`xt>ZjArI{v`{ z-WOYW{qb@qvPW;ZuSYIzcL511_I%arc&S3So$(9HfXBq-K~ALeqK694@l0`Day!I3nYmQOBAa-e&G_NlR8+!7O@y8|_v46medE$?7l~ z75H9K?CWBmYSR7LL!3wPug;uyUpC%#iPRU3eI)#wGl0si!iVg6(7xMAAE_M zPB$Kjl>8J3pjT{~>DqMTsD4azM%Q_2w9Z+WJanDFK+b?C8;959H%VEJR5X&0_Sdpv zkq7>4k!?rvpQQ2wSh#$&!e@Wy?EmxSgYswbzu+jBz}_xK%zJ(pf)rui3mk;}!A`fGzQ}v2hyX~im3JuAbR(66nVT-82O4qes^u<7E zzHeypQus37*(OWE`4M{x%@Cya)a7K!P`P*nUddOGOXjP5RJZsd#KcK3yRxZfWQuA$y?&mlHOA;G3VWrz_lEI}!iIO!K-bpKOSIBRPwJ;kO?7il)sP4i z2_j)lQmY~HK`bQPL@3SO^b)<8iex-AFUswJp2W*RrGxcSOr=^-xWplV?;2A4*~KQx zx9ANV?IY5}5W{NZCQDaDJ8UYFyNYr4%(Fu!R?HnoLmAbDh;X`s^raLs5LR4vgGSv8 zY=eG@GX-JR&vV?rGIQ~Dd$qp0+UxclroWu^cErRqo}&B5uDcRNZE49Ye`S+IN3&>po^ydyLa9r0_id3A-;OXx9 zPH7*@+rIsBb;b2t%cYyPZf>s6R%`b2cUautS_FH8Ii^Gr1gn3j&n!d`~$vC!LJoh-c>z4(5gK4XU%8P zggUZ3`m(_&1WF@&X+5`lLG<^pvj@t*E^pe+$ap~6I>oE5f6OW{&2_C_CtkJs3RQAv zoYyR@cd&8DeZFbfs!nC!?503in7+~IGY4RrV>Q(WtWEGcvo-e)o z9d9a0n`Lkw{lhH?%O}D^JvuO2=lLgvbi$6?i>q{#PI2pP7v$GOX?U2J7P3%wjIh;a zHZ^80)oG2Y^CC{2ysBk4Mr&I@2CCOlF`&i+mO0Mqj#p@SI($DY#)hgS%jrm9eM>dz z?edxR`r;6zmc%ilpdjn@j_>d+Ae=OcvaxBGhvu&dHL{1h#P2+1NZ(l<7ET#E_Prs9 z&-F~mR%2eP*yJkFBSF?}=OU^AaH5uUMk)T>U1(C01;nXZcxOWg2t6<&@$X zO{Pm1x8=-~um=cp&{G92R^79=&0pPT#Rc~SyKSVH0+DEn>Su^F*byke-15SUt$MqO z+}NmG@mq(t2T>YP1E~h~DRyGg6J^N`p$Ksycc;mrG&{CNZ6zNWYG2#Zm*r`<(&E9Q zfY3zPaK?>jO&uhMd~m_t4j{|^ED7D7$Pv%(Nw5E2KQbdUPCbUawCls8&9INLde(SH ztG1v*tFR$f>8n7;rfI1_>#7}s0SDfaK6jMY_ygB?-%4Piy|@sN2C{b$EcOGWs2U%* zF06_x47rR7aD0>*IWv<!hly5|8V(2~WO_Oodxqu!*~yV^ZwQE2tEpy3!z5l5B(L>=?-({7c1NH_kfq8o14X9p4= z=jWfbp8m8-R@*v7y3M4M5f7VW4*>vZ9uR9pc$o=8T{m6j3{SF9vdxQhI(JW*YG%yN zwYLLrIzl-Vb(L&@rlXEtaS#%OD_4eVK+7^KHa!9LYKeP8dC}GqzMh(zn(Lvq%iUOg z+Z4l|p>Op%R6w6rZ5OCql1Z4P&TygpP14=F8CE)wouhTCLTeuo7@%F)T4zVEHMiZ| z#2pdWF*Fj&%?f!(#D_yP)b*)phCi15C|>Qy*i&wk)@=dZ(x}5j0N2`fgD($eQ%{m|NH86&Y1)lr^%4JNrwSC z>V;0WTKnH7*WJ;_j!nRGvya*|&^zQ@TmTQ?h zG%M`#k~Qpm4_eHv*2_~zo5Rt2Zb(O^5(igfrE+z(48Z_QVP*(lBj$ZL{TnU}G1zcl zyHFUQcK|sdx@{76x*tl}Eq+B=nl?Uh%W)^;Ev7+R)+&!IO}eaS*B+SW*!;n$N+|+I?hp3D7H;}QpXa1~->Zan ze6Ds3zdE;T_B(;T;`=^cl-Fs6sz_B}Bl4?aKp!!0C<+V*B`D^ zyg;C+-M9*ZSaC4}L6Ln|v$X99xRD!q$p>>A%qH~N-2T~0gare};lieZWKAc}t5lpJEtj!G&b|u2uGqEusLqpe^ zuz}cp@3p6?YsZ_5jC{IzN&b5-QARj9Ko00OBM&kiz(Yckd1?Crm_ zItdPpz7qit_ir%d4I8*bSDToKF8zdpDt%9@Lr05QGWdx)8yZiQ)CHasv9sOsHZXKB zNcbosMj=OM#79}Q_tVQO%SH$31_7fPKGz>ta=x|3TS&L9hq|H%YUpjDBwz&v2Qs)s zm%~5I4QTX2nZM8NIT|z=OxnM94J6QanJ?^UoNc~BfhF-s5kLE04{LHK&V+p?aPJ#0WiQsW8*&!DX zcAeo=8)O5dj902!9LnV|$VI(|ssz~MMZx2{Uz25PeEjQQj^vw`e?UHacMn21IaJtZ z0r_($#_uyur(CDoJ}c%e4Z|zUqey)HZT{;;$0O@;F)%>ydh$^i?p$7NFUbI}*pxU) zjBdQs&Dzl61s#o%t&11%^;KHO)Is@mGI4+0jXt-z`Yl-Hm+FO!3iwkTf3OcYvr(#!`1u&BUm89qHJI zAIb00)FX|bCu(`m)mD4Xl(XcxI+aj;(meEe0##bk$tlntd7{qs{NhcaAl5lQ#_W46 zKxOTpyX^lr-bMLOGJ^lFZKBFyVb1th#lh60Jz2Pv~!b*p85_5Kh$d=nLhb1W)@jmXv zKr$zxyElhJ*P~pfb2W}S5R2$qhM$xv%ZnZ%bo$gE#x#>~z9Ge|2Ze2r2&Q{akNRLA zG#doOSB(mtnW=Iqq-@APSK>prXibs}Yx)!yQ;oFaFApEuFnMaf_=r1KbJnCHA*9*q z6>sL%C7R_4&_k|&?fKHo(7g@!q8xXU3TgTA6@rKx zt2E~8_lvI?YO(J@Ry}QZ9IM_Pj7;|N{T{qnh0ICF0`qo~xZkG5X|1-Z@u1MLIko1P zg$-@jiy}89lCxwz-kyC|kuw!(VO59i$cVwhQ3RPmm*y z*!+|(M^yIi`?+w>k5579;$*orvz;7AUYrTZ#cOuFz8QStQ)ttPlPUU{pXt19)9z=asMhG$NFJZZ~w%Oci?3g$aLfhwjmelVm0z@{a5+B+0hqtmT&rt1~ zw{_V|Mq;1&CgO;O5Ab5rp}!2=X+uh$GPvX>K?teAeIl4)&E*n(GB1++e-&Z7(yhEs z7s8XF4$FVR5OyH@jgB3TGQ1&{Z-~zlZg^cz5Zg^YrRP?WG7>_ZnpnYi3j?nR!KLqcB$*SZEr<^6Ed~{LD)<`seqr6+ zO&j%P_DJ^ul%!MCRFQOlo^e6HvyoKAHmM<3Q(mH`B^4Eu5^A7a(6IK5if2iC1g!`G z^gq}iq#S1el`GhNvGx~e9Xb4=Fz64G6#nhP**%lRV<7&+g*1i9f3I!9KiUHMMTx0@ z(pcrq_s;Z3*4@uJYVMfZ#SZ$v%x8DGP*YvEqLs?fb7#V*eYvLjF&x zPr!+X_bEHF8i|u~@~?6Q3IJv9Z=~;k7ok#4K9a`%2aWFE5>BtO{)46+w_p4pRSpzn z4*rqJPX6+@9*8gukl6SnY?1AR@C}d*{!c!CQT`K=964cC;|p1jI9|z@4<6EV_^@^< zBE+2RtmN~Zwr7PgK3m)a+o+RkO3jpx>$`1$USrLfpu@ zZQGqbwd00geXsI)0@1GFdV$(@K1YP6tU8@(4Yvb*@W&KWm;-NVVWY?~1)lx49o)9Fl3XAHY1Y}u=oo4rSds8a1= zA5n7{txgK`O);mayi#=yWn)fJrp!{X)HZAr)ba%&U>;73d&0>YjmK5g7IL^Xvcc#^GKYmNHTg!Qhrg5($ zHs(CFr9x@(lfYMU0{anE*un=k9kUn^6GxbI?CXqP;_+| zt~=EB*joRYpC4-4A0%)!QTj__do-rJ%v>e9Q482=Z`Ow@@87Px!vgaMG%3o=wl@_z zThGM!DwHU8k+4S@EP?qG+==L@J>VNIIqag+o{eC;8VJT2L~6L%t* z{fQ*RqURLgD}`@h%pu(gW~b{mCL8D%e_lMsF<#a#@_r_)my#UzjR?FmlTX0})u|9C ztwenM#iv^St7TSC-Nx|*(Au$zFVTI!FUR-X=*j9iDdek>`8ohxmS@ z3DYb+ONU5?}u?J4gAW-$Ock_jLHz4BPQjm_@IKUX?kJe{YR4tBvV&1%RTRkYQ8 zDY$jY9+%QX+Ivh7F$vyD*myBJKkVY*Vbd^?;n;i=X8_)#hVvwkdS3|94z#?>GC=OL z+oU}6V$VBfSADs$ZIJtj&F+S~Es+|1V%d42+8YkCmnS}5rFM37Vx~zr2qZ-?I_(56 zD@`${Ur?^>dAAX*lq(t8@cCAZ#JwjqJ5Rw!&zYtnO&lLJB-zIuPJt*)L(3ggP>|@yHTblsH%y2)*lX1pxxX&btDw&j-lGFYEHfI0*m%{@FhX&gEu9O+{RmMm^ zj<4EF{@)bgNFueWb6xac#W(FLN9;%~tjg@Q6~AP z;xi1ciwk?d{xVky(2|g}CR!tHOQ1&J_U4T#t-s|ddwFbVHH0*T*@WM#qJmE-S8nU` z2WdH-M<6ndhPT~t5Iwh|Zl&mm^__FC+HQ)Fy3Ie=$U{RN`Jsx&)b@s*q;m zomcTVN3nnPVMQu=G@+H3>0#Lq-i}<6lSX2EFJwg34gh zOgiw;BJxY`*A zU4IR-G(OU5FnlVwy2LLwBcrpg94v}c&}# z`P$^$2p!a8f7O|b>C4$fj|fMX^)Zpsp=~=#LK`C1r$7%JbG@#03X(8BT{oZSMrEk( z#AH)(qv6`2ho}~XDq9b$o!>!f!vrWNe-1`0uQd?8cN(vg?P%kw;; zaZ?EPxalU%mm~$SJs$)f3xt*(PY0f@SgF5+l}_$eIo2@hZnDPug})1b5py~f!S9w2 zLRdfDSXFOKU@cJbwG8>HBu)4+MNro$AIGe#u@Pm&60tJ7DPvJ+CkL{uZ|rIdkOayJ z+nzm7VFu|aJxz}Mbo@G31Ia?&-~V0BKU2DQv=2N+n$lZ zkyLN}OaMDS4m@%_qP9|%`bc+$XayW7VXjKEPMtp+k#MLY)yOX+Sj8eQGk%I3&49Mw z)dj-{Ym&mY@4}q-EOYkcbTz6z`4ZgtF811{6%X@(NsRbvo5Tot=fdBZU@ejGA?Bod ze{R=LMU&s0J^pu$zJZd=+e$SfJwa$WwL505eisb?qX4VqWI*vCzlqu7 zwZjIz-}&>yat6G|`Gr_OGOWsjC(~_gBJW=ELp7P0(hLiEjgg0+#O4bpM$>V3euo`< z2hz9BdxDyOHj3%*kxik7QXh?2BtJ{BT@idvQAx7iB9VamAu;OyMLwcIkqYm-qccak zlJ$EcamRX4`zUec(AeR~Aq9cVNC7{_qzQ4S%C;1eJd_*fAnWAxYrQSpUa%o8ya`)` z>^HkjG`)FY^n%>ZZEVuvt$7jJjU24B$EgT_@3-6JI8~#PS98oMi$j^(d2aCb92s}f z{~%>FzXJ4W9ySVV!Lq~haFdlQx8mW7;^uOfDhgvw2XD0Yw{VTQMTql;@vtF$`5$7A%P`{=uws+&6EI#g}8KKB1-3DA3lw0al>xVZjzq?9q zw3Z!K!u#w9i>ne{aMLnQQ4{&tUf;crx?mT>spJyXtvL8CnDJNm6g|f={dYhSrV|Mk zPc#`NDCS!GP4+|-f;3K4U9tF<_PIx}$3nL-%AW@J6?@6u)0Dclt z(56B=K0;yc(XZvUilAF0M#Zy2y~O$@A#{V2G2iQ10){^wfgPp=FLbx z4t|SC&=epXxT)~hWt#tVc_8m*rY7u>uo0l$0fb_pPDgp6k>R*Mk-q+-0}XMq!Gb8? zvLWU`G3;qCl2<-%`~NA<0Lp(Rz~c}6090(>Cu8b>^hX%BLYbUpN)UyQ^51nIzjH}l zf^@tB(amCl+5s_Khld#F8m>pA1ETde7sBn|DZOokiG?W5Rb}o7{veHZ+euyB0B^l8 zt22S#r?2)iz|H>n^EpRCYHCMk_hrckm%+2x6o0`kSWQTY-M2%7sW@(yhI-KW(&dqW z1DFmn(SldwLn_M@Pq@BxiA9+{JY<3f4jay5mZbkS>n{eSeYriM@*p+feXfc+*7J0k z5+$6~U5PiR2R5eQu&yJeNLg}k4?BQ&Wy8h??D>O8jqPH~#;xa=`-qO;%k90u89+Df zF|9~7cG$uX>5@XYctA*Jn^q+>J@c>tIdDG@?}pnx+nrZ~ZcjQUj8JmA3}?xf&@C;# zq)YqJ<-rRfYL!KYE2nwTNkJzu+1Dw*w+!=RHbh?4tw*C+Y#lqt1FZU8jE8i|7e^UB zxi8@A(Hva<@&Xy*!=GQ|c;OD-M0hC+5X@FqaCqOa$f9a0h=(d`?L47PqJw+f$%3^d z8Nh!1>AGYsbhHcnv_6Kd3kLh+5i|U3CyZ&#IvPlSkd&V!&`=O zOkTseqpnnN@ik{Il~uLCOjVQ{n#5)M&@~_*boGu;L4%W<-(4nNLthQg#u?W zQuv+RMRtG^%+--9Uq1*s1d0}~bN4UFbChZG=4BGr;CoMmK{|w}giJ;I+tl2%!v)JF z(!TG93MhN2$_fu8($sQ&_A(!L)O&*D7vIx*m!Hr%i&8!#$?eYrfBrD^IUh)xcC|G& z-uai4jtQ>5ePaE?ZMQ~Y4+A^b&4lgHr0%q`7NMd5izu&NSplseKtqx=?I{Z^YwFRb z)u&8Z&rM09J~E58Y;X>L@Rklx0aUm0ASU-rErA>^BugyG792dP?iUr$RNS>q9nhee*CIBiSFy)k0s?=Q8_Wm@oLZVgak8mCLeslRQmqe#qSy-VM^EIBvAy4s*qe1yQh!Y?4tHQp%1;%e2)XADYl<9O5*F8;lERm=sU;bP zs)7cB$eWbBmc0Na1p|StmbP|%mex5gXD-|xuk+WuV>V;GL>0rKZLVM{=>S@(#CvKd zXxTlXWUX`iaYaqD-ybBu2py}DV}0$Iuuy4cS6r}hEsWhL1M1Wg<^SSCF4go-IH!O~ zgRzl{V5Jr9r{5#EdVZT(1I9*wI5Dt&NILjau?c_;?`C6 z%MzHg)L#m5fR|>Ugbcm^#w3E?WiT6LrA`R)=aRy6396^sR-bY7WLH(3>dKx1q$?tn zNl&afNgLgnnRo`j`*<>fzmDLSId;9ee>s2o0D4~sH_qYA4YztI4&Z5(p>0Yy&^_Vf z?IB1-%~!rr8|vL!%)2*5Pe1}*ChxJRvsFL^z21>leq%N3S28TJm2v3 zB(m*lj$5Y(dy$z?b_xLMTbL4OF;|@2Z|3+Vv~UG6XYb#hHw{*i^H$CH+M2ZniR}iH zn`hHY3C?Wa0CI)HaVL@t_VmQ!QsoD8hbTkw&}Bd4Tq<DUmCZF4UYw?-E{ZO=_8OK zb6(l;L9Z9BQy%?3=YPKRL!5QicjS#<;8+EDqrdv%ipGpC6dPn$c@{}!5@!Kuic|9E z`1L)~biyT?s>o;74Gz-g@5wxv#VF96So@E0ht zm3&q&=)-HP{0zHRkl2NNjeVGc^Bb!cpC55gX+G^$%Rt!`er!uOR^vEXtEgZydU=`g z*?_CSPAzS5t5K=nNZp(LJ!(>2rhU>qdQ3nD*k{@wzx;rn-0L~qCaUQ{#^s9r&W?*? z!MZ7&@9IM~ll!rW^- z`fPTLcaqRCB|glD=mH9EwYSi`&wwV&-)l{fAOT8k>p@c__mhB#?BA+E)FL!cx*<&M zfZf1$o28CW1OmMK6@lFlX>4G+(k|Y^)hA|w;|TERB;H*Cbr_IL5K5=r`!RvmssHHW z$zSSnUI6|7-35Q%KZ->Jvw}B=h=BrC3oY9pK~k@jzO{B@2Y3P7O;31tkh_*Ti=?ET zpx{hu*z7k+o_o=G$>;tg@W{SZ>P#o+PSrvayW}Yz3lbL}Vg=ehNKE`PgX!;g(w^z` zg#L^^HT@8>pVdJv8_a3PDMqK^+e9ZLNH%6`$i3_r7Nk2=CcU+!cJvgc@Y8TV^zc$O z3nx2HXJ=-r{Zxx3`&koroWe*;G&! zp(A5@H0WN^E5svdeNixKiP16z&xU9>mzV!aMO3P(JWx@`#*V1=okg(oP(d<-<_LO5 z(BC`}Le7G5qFg(`al1+(s?;W3bJno#&`y~eaOlj*SMZq&NFVg;amqao$DWXT=fYB# z#ai3EJcSil_SJIG+Wz?G0z&hh%4Ux3T-juGA1qtt$yPj9?>oxf1NHL818Trx>c#$r z1&^b2&*$=|sWldlPhA+lCrs&ok$tqfiEyL^sm=8h=fE<}IVRJdm-JBosz*5j0DbtO z_d?}%E0S$hAbk`29%?;if903y?{Ub>j3z2ux11Tg7<51RYXd^=-Q8MsgAnHlW5 zv@{@BM8Njcnds;^d7a~8MWUh-WYo`ZmW27u+?tPZT|S9=gYF?ekQ^L3HINnK;A#LI zyc((M9qBe$UtcH5K9xEd&zuf`_9N*MY~loR+ll(bde&k)PSXMQ0#U-p1*nIe9lpChdI_)QI1=8sN|;D$v#90!&`a{8m9?IR@~uQv@^9QsNp8zk$w%Kt2uW?D|j71Z49R?^i0VP*KLH8_U42t`E;n0`En1$ zr;B;?T4KxqzCE!&vJU`rbgEqz7p=-jHfa6qJ;{>OePUl)VtT$g@pw9y8_{Jm(`}O& zMdo3fC0OV8^)QeYw!Ro$9KpuadcmE)_;FA8RQHr2O3fmP>x>6?t8|TP1izpdQ4Rt9 zK|((2l7OWhi=LE3+IhJ5Vf1*QvY2K^ZGYIRG!1>q#8is{>xSS*`-^RH6Cv=2K6Drz zQ2n@bk{om{?S34a+i6tsZdO^%=X!zGKUQL_Ask0k@lucKL+wzjX9st}y;=dW z#<~o(mh@jD=LPR0e5qbX3EpBQX}&L%K=KI#FcqpQ1`RL(qOATj$kMKxVByMBA2LsL zkmbj2cRHcVduwaHiQ5@h0~G8wi(CD|Wh*HZZxjUXTP%b-4-tU&c?p1Y6~sTNlh*R7O1~ zJKM+7XNP$m37Zl`-Wk8MyJJO^jQ0Vh-y-8mTH%keP(o;Fmaa#UWVsiA#JwU0Uy;_T zxeWc^fEeTeKSwL;# z17Fzw4vKE-#?|}v!ML&%WYS~$GyM^wI#v}+Qdh)UCfmX+h7*cW?P`K1jts>Qmc(xW z>IdWeQg*Q_U0NC!3U}NW%4i`Qsl&AXI3)Sjs_TyQ2cIIp6oXhIwZHMgu{gLJJCGXe z@<^0NEMHnu{(+@a1)CjP+0r)u)r6M5_~#oYcCropLU2PS;V#FVaCG+bQCm+=RKNGVvc{#>Y-j(^1s*5I>&S#t&&?AfIrVI<2x?WX`7yKj8m<{D4jV5wB&E!6ikvNWRg-cMlR*$ZwVuBz>_=(g z_%`-;Itgmy#?}ZZt>ABL-=f@~TUNeSEh+1JNl)aWNk>edYLx`LXWg8H6oXA<5;Ye) z*#jKP4{}*!`{@|w29ig)KAnResy5h5bf8NhK0|avde)R)BYo6%ljBurb|4AqCPC;Tj)Kl$(25&w<3w~lHv zdiOoCLUAeX4#l0~6pEKZY0=;gAq3Z;#a#-tP)c!%OK^903MFVlp*RFu2t_*i{q8;M z%(-*U+%t3UoHhSsy$e{Iy;k0x>~}xU_w)I++-}Hm(#YwWthi9@ey(FjwQB}GK0`(; zIR^APo)}#YW_&;BQ2U$@3@AE@nst(JSDYuT#c_{QedHB5stw|gI6w<#7m;uJtVksP zV#EivMnEU?l?IKjjaOWNb@6~>zcjiMdpp-k`!PPUEZUy|2YTN^i32i+l(2eO@7QFm zV&!=u#${XIVZ?M?fEU5He(`(x1TXyEW#nX7eW&To31F$CVR0}(fZVIDbG0b5x@5FK zMza7w2xe+-Zd|{~m;uEwwSq3bk;t z+=w{USZcEeJ0F8+>B1gG@PLn_StB=55Z)2s*)g5sO*73YY!u0M-+tr`-1Zc3bI$qGlfg&cveo4tGAAA+`O;}#m=XP4?bOiQ0 zba}=;*PAmGB2f4;*d&%BYHmJR}&Yq`P>hP=fMX)>+P;eM289 zAu?qDzB5oHia#9Vrs>mOSJPV*DdOx2id`w@(rllZa8BrVBEyCnMDnMq;B-yl6Ir66 zghm|!PkvD%qURAmlISrddYd_0lrWoxlVl4b&)~~YhVRgOy+P4gB3N?wQsyviv?+e_ z59hKJlNF8t2gWBR53Khey59a7jo%vVc`7Yyl~5-yUb$XdX$E}11Z6;#WgBLQBp4xP zXbZ8i?bK^7v6O=_H&Llq>F0X|%vr(kNvo4?CDZesZUiuJ!68v}-^y{z{dLUt=?a5M z`fZB=trJ!|pl;P{Tv7ONQ+z>E)dkK%z7N~Tx{6OKk&S7Y3#q)A`W0vXxK)p3!zC;T z_d2a{j#PU&RD8HZc%TLb(A;`*X508u8}BFjSqPZS2|XZMgZ3bi`EArtx>ZeqE>GHxF}C(Fg!-x$l#FR#1`ND;Eo<0%TtPE zCZ7KtVyqQwf=r3ElNWcDO4soekNc@ zoHuQ;2F=-5LwTS_>ez?L>S8x!t6r;mM9S1fyLy(Cej!T7|7*pQMpi#1$;x~JN19|2Rwab&pa z+iGBl?)?V{7eXmEC-m_-bAdyVR8`G>P;H^WfR-6jBJU_TJH-Xxg;S7{n{$1L_u007 zHMY}zS*H48*Bc;0kI+Im0U}xX-8ub0)^|#J3nu-i+C{L$Z}H*8*sI6>a+!moN-lz# z@lxZ;X6086i`Dt;yWeXT+#@SPBB;6n@8(WDsk{oOkl|)n6Sg;y<0F+PyJr1_twE2O zBt7P;@Ckn4_J-}58tMq%zn#gP8CdMiPIOqf|&O z&66P(%q|CH!JE!D)MZGyP@05--iwxnUrO@azER{B7SrB}D?;r0^&<&|V!I#5En>p` znIEC@kb1*4Wk+VcgRyfE$*TUVILCrFF}f-+sklkHF6diWG|Hes_o;!px|l|R*&Q8f zxDu5IzduXzt>M;$V2fu~m@GjuZ$;CZKz_sY%{=67%M-Q+h!T6d#6NdbME-j zY5T{w6QAehOrC=7obA2svG;Ft=54vNr5qj80@oS?%J*DTX+wC#%e;Q#>>mu zU;}fLWAaLxds>P9_zva9Kw3ZFP8deKO|JHn+T&|DbJPzcC3={75Iu)7i}o%+dms0+ zB-Mh<(BfC1==rTGj#vEd$eh~7y35! zaVO_Saj~_vs>eGx;glYgB1I<5v;RqY(0|zX`(J|q64#*KIQ!PQJ10blULU=ClCOg13Zk|oqSB>-2mm(%d8 zk7nbAF+*nKp5)|Jg5Ta3NcJ2L?bEtx5opobEg9HkiZw#|2)&oi-}{3q;@?7EmzcX+8^l>pPu)qCv}k@IZ6#H@@N#WFU(rXj$xyT?eQL_{w> zP?4?$Bzf$!FL8Sy47Og{PFUt{OEafZ^h)vu?sO{#(R(-G=_2Jv|0=)2x#tOp-bv@HR6wR-$|>xSq4TSh z+z4iCdg}!D2Zg~4Wp0%*(s_Je1zA$@nT`Y{-n83%^#vMFJf75?&%xdcJq#W91@aC% zsVoIgP+QLzR@9fez@%})K0n)U4aUny;n@p*uX^;gN^V~**vY8U;(3lNm||Y@9hwEN z3l^CVEj9*5iX563KCrgWY=vea&*BvEP=jwk%awo-R_`oT|Gq=5(4h zX3O?Vt|=(>k`rvm&W$TmC@mr_v)^J~6%+VPv~r zn35M;5f20qgY%Zo?J)9ylr24^(bqC(*_n@?!C`(YG*SlZ7BwTeF@d(1U+D*MP5X!ia2l)0|leJOjgWFW+xA*4e+V!J!uvfI55h)w5Ft~fL+wOA} zd0m5~<4U{cewmakDZz=lQ*}}_3!8w`c={PT2FdI(E9h)7d+CiEa$-PbwxFqqJ)w3U@FwRTVc(`u!b%T#1;{%cv_mBr#V$C zW`gb{iCv09v)2w++Mv=f{6-sVqA#Qh9OB^5Id3-0IP1Q~`PO5Y;kFuc`qFbbuKQ zNLmi7_7^pO-T-?#Jm6+*!VN6pYSvmhC#xYNzVMppfKGL7(*9+hTU~ zas6rC;bN?%pg2Ha8H%Z<$j%%v;aA zJu>?FMyS=Plll1VM}GzDD`2?-gFH)aKv5%}yGPcxi3OzpKe(hZAk82D|%C(_iP z*V00SR*V69w8=qib=|ic+Gz3A^w;*c2afXty%!4w`S6 zS1?3s?A{HvsBi|aId6W)t+s%Oe9*ctMwj4Up&^^PHL!6`MSIQ5f#oxz^jL#^J3l(2 zYJ41@ehF+_;e<`Bw)RCgkneL(-zxrYsHmDiMx&~5I=>hn^>fN{`_jIPS<-}w^VC6X zc)tD7;vp#5U!G>%<0ZRf;MwWJH_il1IYYg%ud@@F0szh$3`5k``7lB!YS~`}SvoMr zT42-S2NRNZ8%<-_b?N<9NjBgWCF%#!ii6=6KJfy z{k{>}X$`(4pk13Xsrw=l2uO;NG>N#8Qb!jOnE{-+m{p~BW^-pX0+MUvMT^k94OUmD z6J{TOO|utCq)&@6GleKcWE@%f(!5Q0wx>@vQ%g-mGSA?~ZTf=Xo-SBD8;$ zPd(dfl$eb%_6*408vfH#E9A@eRk8S40x383bVPj$?NVoBCEL1=xVTgxHU>TByztO0 zwpLkL4RvLP**F;Nl@fQ-BiBx(?}q6$%bD<6AM3VlEf?XgNM^o{GFTfBcSTORlH7pn$Iel}{6RcZ5m^z~bD4^RB~mK%EJ| ze-Q><4Z_^FI)}>B{m>AG?Oxg!93O$N0IAJ^kxI|domDrX?(%h;?yJdNKdA;?mGIn~ zEpS7`fcZkpe*(K^TTBlY0MmqzlXN76S`}?yedMwV#9+$v`)!7~6%dRdNk!<9p<)MH z&`R(CzkrjyK=yPFzYN;FiB4WioNznN&&3H7iw_L_%vA{Pjw`8$=X#c>yZH>T+6 zE^5hQJ_ll&)fsE<3$fX( zH{B`UEHT!#VE6w09W8|jFbPoB@V+@YCpK551H$eH?23wErl5SOV`k zn#_N%p(hQK*bJf)sD2%p-$XZZG65f1Q~I7wmurg zSN>U3aKwX*QVGu5^Gk2+FGjK+dX4@-ho-`|xYNkO2A+r9FWsf0zNMlxxX^X?orfC< zOsm__+uN@x^yoi ze0R-qJ^tnKKc@U}7^-pSihfxAm$_kV=#0Q{V+n{Yf0PbB7Nzvm639@PfzywqSBW>d zfwP{oVrh;_<{)PAtOD}1Gc~eaAss)?zxq*REj{NCt*ry(S8lRZ8o?){_Osk$Z4H>bxJxn1%13DGX zenD?r4TkqDLyAVH$T#9uE7l)?f#F|yBCE?eyD<*+hV^g~+5E4@{qu65x6-TbiYq@y zX|v|m+%6+b#?p30>tptx*D`3KBrBcip*_3{lHU=_jvd+C9|bJ|HcZ3SQWwJwdt#rh zwWy{#TkRRYqE{2lS&7_DQUUySUbqD?i(BRIu5C7Ma{^V28u2I22K@A;NPIr8lKC$*PN+#ZG56UU zX3n0}SJ0-wB!hI0m}aO$%-*3vr4g^)rw^;&qZzz3ahrbYy`#?gqdSuh{@UH;ugIM9 zTyQtmZR!@bouR%bnDO>E=ck1^k{00vMS{;WI&I+mDP!BAKEb`)*X^P=lk{uHmnKlF zF7v0jN}nKID;x;ncj-XcrA_vf2k`*mle2A|Jh1E|=j!Cd;)-;-cZC9v9r(T)UfK^z#!X$*F)*-i!1eAHr~xgGL0kBw6#cBSu5-pc|Zo(di}KW&b8w-yymo~e9p z%q~OLw074oO%Ww35EacjM{2q(|EAE{%=HkKJO>D*=iL#F$=c2E!qK8vr_2A84&~*% zs#P*T*%Yk@gz8EyOzKImki$kjy}h0G?u(BLRU{&%ldpy5UcZZs#qlZq!XSR9cAi|b z+nhXnq$WAhhjMmcHdt@agj~EK3rr#SlHBv@a*~F7_n|G z!q#^agHH*?)_I^#jahlU#ECw#q*u>(Yt#~PA=>op$e620b)Xd;4@rz+N$kvJhRqh+sCu>MN0R#h&)#~`H_wA z3Dh13$;ykW-!f~>mF?RZZFfZ&Z?+SA!*#FYBm?d=zHYi)2PF>|d>4K+^2xC!*f*;* zNsasyrNicgzj)QVOJQ_^%U6l)&gLu1N_Wxz{Jy69_vzQKrUzrKPb6ORzzSUa?2W;0q)6(X)8UBll)doH;HRnlt3h_2_STZ_Bu8RyF zVkWEqcI>;szOV*Z>}|4-PhJaingvyC3Vz6&5sgh9_j*||-UoZm)+h+<#gkNeVtUvb zwAa%rdsX7ItMxGQD8Gvy1l!agF#Cwl&l!GGS|YH@7+(2^AG6K|iD%ln)TIQf9W7fo zLB;It&G1i)9h|bI?D5`xFSZ>kzD~$U`Wa(rspHArd;Zf5sT3|L{CMj~{{Z&>l)HY( zXOgQGNciD{7R~`thISpN7si$-Y|A%BJnIV+%R71NO(EItbq`M2kg`IBCGml& z`G59IiMRtHzCw6hO4o{ihVznHxR!(5*4>td(+bb6cUb9irE%%5Roih{0|yYz_F)>qh0SuJkr=XP%^7smcZ)vcL6->)DPY zFLHQf@{`m0^Ug2}F$F3BbVnyy9&0sdmUu`u(xSuF32nIqbUzIddmRBnkZ0UwWTiKWCy7s|}>)NKYTzob0rMT>L*!=JMEvi?qm2ei#m!7;u zhBkATD@^}xJ~>ZNY8(|iK(;lu#;NZj67WCGDEj$jW~_ypNnk6zK~?QUo#W>1fP~c+ zm%SyZ>9ew?*C(zz-feQdZ{R2qU}De8+hfz=#UTOuf!`T<9{f2?Epzo+bNMq zv*BUW4$Xb)$o9i)is!XD^vyaePqN7;Y&>a*+ikzE-~cKtbe9V$03sl&_J-O$t&07i3hn~!f9o3!f~;*0nI zGps2Z7z_J&Ry$!dYTI?BicMVAIoG6u-8Ie7XQT?>)~kp_W6(kuT8C7EcDp{bp0|U$ z7>TFbaXwR5ZsF`%Jn9Lo7?vkNTA00TT$`lFx{K9cv+zsLvWZlCOhBKSdGV5$n z?`IoqtWN`h<^AQBT0AhJ(;pYvG%kgywqMzDE!C$-ojGuIwlD&!hF}6P|D-Mr#+BDP zAa6Ux0((KlNnaP%Y?-TZ&b9CLm}&XZUTr^et-b$T53``-J1cLSk(SYpzR!Lo-W$KV zWm@a5Su|n)2r3D*)rjx+Wov0{+->7Csy+MB-O3wBB_efS?35-EUsR;lZ z4W-nRe!noWpuI+E-$qbOfV;=FfmwjiOPN1VBJ}~&xR?pF!fNY0!EWg4Y{RtcW{_Iw zVk?``n7H_kT%4hKj`=V8*?udcL*tICW}v`wM_nA~1XTW^bDTgBn#dtxv>WBwwMO}J z0yEP-IR1N^8D{tvt?wk5%wjOGbTyxulw1w|jL|8H%pz9E2~B_O;#D~<5_U_xU+Sq(*oDU4>rSPK>i5n zWC<4X155HHjyZv|vugLVlH4QxTv{bh`PUkZfTH!|ftT&i*1~a*fB5u>phBvEJ%aT} zzvPP5H9aRAPg~pW`de3#T$5drwruv&mjP#KAr;C#n@^Eu0n+`~p}gO|0CO6nY5Ref z5{vC`HH(CyPdJmvb*#Pc`=+gra@9+BKXdCvUf-iA7%9#DVzWml$B^npyNnc{-dRtVVWUM8NIF7!6LU3sV?$N zqGNXO3@ri~$VGFKbr79_532-fIQ1??Oc@${W87IUr}so*n1;MvpJi<#f)T>0zgZq1 zDYDGF;pUSs_k1_odD{Ur;h?Ul3pWIKOPzkQ#tOEr0EUs=In-_L|CuSQJ!m|XmD|MG zDivSrlJ+d35|tchTPjnH{XrphU5N2n993Qsz(-1wn6F5z4xDpuR&UAg$`cf0s`3m- z8vjVeY|{6p)hpZWu1#$H4$bCJt2m^uOF1Q}kt!@#EB#P2wJe2%Rkr3PGI}${TTF`B z1`xu<~I1h-Z&9Wz;hTZuu0kol?Bip9-!GI-w)8Q zKEIkNT*zF5msS2^NUXeBy9wZXhDEk|_Q@_K@czm6S==3$-4`@elKM&YL6FIU`pp9!xqW9E0DRBCKkF@#i?@}Q0C&;^_f53U5mrDQ{FzU z5^s7011o=yNdy&{V}-wlh|Wr^luCki`8DOIMz}kXcM^pMQ-~k(Sy8|aA9xm<3vha} z1hZnkx_H}5VsetiHL2)7i&MNzI)BW3XMmlv5GukoI|N24|4tT#qJ-Sscp8^pCd`>z zT4)F~n%c#f8a(S79veykfO*wirqA;WpUv3(VyDH^1Q0Q7(~+u z9nF)v)g86i@eSg6=XV+f3VvgieJ7sb%CleAAS7r@+4*Oy7{Mpn4X4` zTcGLOXed-c$@rM&unlxlo%K)n0s+Hocp`_ zI%B^hC6Q^mEVtzn8Wf2m_G-jd@Fv4ivbRP>?K=r$T#MwwTyO=wc^_wJBeZn991Co!R537?F z=CltgQ$1!vA~O@EF~DjtLBJ2^v+}_jm)Dw$;#3x__t}~jXty?g8)wVe2NBQx=SNy5 zBtb`r>~@;OU#XAoGj&>)gpNUH=H`c_^cH~&Vp`0fA6^O3lXb4A^#zz8$TC3<*2S&3hm}+BzG(DLDV~IILAt_^j^!@=e%)Lf}2>FNXL7B_`?BUg`aB z^offr7^P7c*2}UNHW1GCu)Y-5(|bLQMhQH=|9QQ0H;cBlE3I{;UavgdP)Xl$tQ2ge zUMj(rsU(%CT{}Qsj*IH;%iO_!In=ktVsr+)J2!FIp0-m%aB|aB8zXtG@__y>Ht#YN z-{JD4xzFmOVVFeykZF(8_cnovc0N*uhEFL^zdQp0cKDrp9wS-ePrIZ;{J)|c15ex~ zCOH^qE>$tw@7Is*qSS4zH|>)m^d`Q8vojyal&DFggGR$o3Kv1{zn|6C3>5+6^%J2s zTthPlds^ahG;a4h-=Y;T_G=&b0>IixzJOqhw%C_XT&`A-vz}t=byx9bY_xcIe9DtP zH{rD$Lt#V^hq{pVD40Eu+4+Stjm@&@3;rIJOSLrVy9`f;N0XS@eLotpn|n~PA!VrC zMa`Z$A?t-R@W@Bv+b+AQcIRCENnHOAuNFQ#S@h+1DhBPs&v}OEAnt!!8obLk_m_*0 zJIrF*QuYSszmV&2D?0CXrnfr2feP5Ge}NqDh5J0Y1I#%tpF)*L*pN6^LB7+swFR8s znzLXr6;{JBhK=vx!;z8YoVIN>gz)mARO0Vu`OJSYG!kFWb;$@tm&pO9=05rl*|xW- z*~=-%QAa=i`3%B{K980ojbr9rN+~acq3j-b%;e8Uz1^Dh$)RIqPA@z%VrHLrlf38ClbSS$4-Lw@5cO*GWy_+Ow@^M1|@~fFr^s!+Wa{hq|h+ZGF|80E`^sdR~+@Y7ks0PZg z4yAFX^xqZ(-(L*3L#xY`zZgvDfqLOAT@QC*AODdYs=04MJ4LPL!lF&lhm}E>x5x*l zJ6^2T|33cn2P&rr^4otIe(RsZ-{YYS3(za=zYoqI_Rq0@p+^pbGyg{;U;n!!|I5Pu z&rbYbhp+l?6TkBbi$;Ir{_D&~vc6ibZw9{6YWHgx!T9kuTUKzot9n5bt5Iwhe_b4H z7$asG?o|C6TktZMg;Xm{F^9Qg<}<(ofOjcQvt`mcf~=0MN&*oWraZahS{7CPS5Lw$C4PEtD<0 z(HkcxZ$Rb5qOjyY#$|}_HtcT&^Ywd4l14F0taQoy2znbgIW9sOYDfl5iZZXu_Fp7> zdzGKoYrYM1)*QF{tZXnwYQ7*J0$$W|X za-ZZ7x)tv%@lFddX`vEgM77}N%fNpW5RuL-(VA4!@Lr#4<9m*&Y07-`W6`#3WuWvh zPzz#Mi*kCoAnZ$C_&ub09T11+CP$|iXUwd-6D___xrqu-Fc(7f4_v^)`lqe>bATb+ zOkQ5F&}69s8{8_19DV#v-2<+E3?06Am!iVmYZ>dAYH3W8y+gMZ$6d;~b+KTMZ+D8U zPW4dxuE601>L@jK(92I`w^vakdvcHM@ZQPu?C24rfN$%2bY*`U_JCzhqZTs*J=ssP z0onEw=NM|rhLkw^RO)2p<`9cFUrk1}fcCA`hbGNjW^3)P}C zT*{Al=1d`0-{k+W{8n`As~DdCVW1Jl1*z)WF18|z0Pp}zFZQgi zWa(7m$OME|A>Z4dP&^Wowlqn)(E80?8ZkfrucWX4UtD4Sm%wrrTbW>YwO6xzqHc--5T&$bg z!iU%+Q_=Y!6wTlR*@~b;^O8?~@aqr_(=2OhSaSY0ev$S{QuL#=bod9k`*M330!=R# zUY0V$^VWngXO?(Hie-6^);ZJ7>2l|5*_1@5@<&U8-_6Vb<04%Fj2oj8Z#0kJjIRoC zD+wk=hs!A6mi5plUWFsM6A`@7Y1LtR^=5b{$X^B8jwE``N&VTV4kQz-;mQ9ZqvQzF zc;lK|bK;Ec!!Guz8A=siH_8&a^b|Aw=#aZMn0qH1(g@ho zFNTm9nUcWUVh!nr`7y6UAdI0(r~^ehr4-v0iNtQ(+t;nl?F-bL(Oq(2snRR0l6J?e z56#dperP|3Sn^N_1aAUwW13xIE&{mPbFB==?syNBsA5Ct!I5U(R-#c6|W;~H2F~U3W4fu=E-%E+g8&WA|Notf9qjy7>1;fhuIxSEqzD-pwfUh6%iVH3(Y? z#2?j(z=r_1^SC3*tz1qJKof}*vr{>%MxBzG^Y6MMvoQH~LnE!#IaV$5V%sQc^gZ5# ze!~=>qTUVl2%!x90};#fHK)Isymh-{t~O!9&@I!UYQe#NxwR?ncpT6Zk!J$9yR7J2 zH99nS>tUfs(plcr8=h=AtKUM;=h|U7JsqjSnt7|`HqnLewE$H!hcpEm#2CrrVxkvf zA=UYG!3awtwWVT?%93xs*rnbA#CenAvt*;Ft~Vo$?ptvi5f{5mvEPgD*!=1xpTvpF zd0D)Thgh1dMpK#YbbHTz%pS_ifK>=EZhzh3)3QG6htXcAXli_M&REdsNABTF;5)({ z4z@SSA-(?#x6A)66gZVKY^=5NFUCsg=tH9G%>R3KxMCiXyBWSk&?j8N5CwEJetrt*!iwkp;@1?zzZfPx2I4UpaN4QDM162N zh4KxvIoOEzEfynW;`<=UbIIKv?98FB9&VDRzH8IC3#a1}lX;zQTp(7HIWq|-uQ@IS zZ5i-B?3aGn&hE37z^giXczUiEnftBzXbmI_$T+~N$1)YY)M}ulVf8SHh*(-lIq)_| zsg9syhSM}=OTY2~s*MdT9RXaOOM;xxT>lLI59*Fq^4dv^PjSi^lel#-kN>DwZEyJP z9V$=+>#VwizI1#TAirA+u0hbzg%4I8TbJ`ZlZ5xMHz5sY6MUJ1Mzxo!p}{D5d0~o2 z7pK!DUX~1T#TO6B2D2;-1_ygq054V#dUT=gRh|{o zoL+f^OBU006DQCf9!Y7d5(Hh8V_^ph8rg$+Do&G*$Dh z5}x^CcEW?t3fV^7!?5pF*EoMjp&(3;)rs|{Gl5K|s4v8#&3MwEnG6|nmcZdsD_OF* ziWN&i-!2i_dY?hIpjs%B~I*a!8-H+ z$;EMx0q5kKlmq+Z$Kj0tqN&B*d=uKG^jyf75P&Cwm>vc&;qFRO*c~)e!JN5`HnL-3 zqJ3oh{2<|`caWYY{+C?p@jd(6n@C?|OsS{O3aQ*$cm9B-mOK21Z4JI4$w@u~W;>-< z#BV9M6@zN|omS5C*4UTKtT7L|LO9DXgceS6W!|J)_gCAuwn|WHXC>d=lV2G8m{&${ zOTyxV-0alqqd)FNu%m9LoDf@V98lU`d&XX5qD6IL!T{73bkpN!+o&46f9$1%8zkffbzxk~Co$0wTQ zwPT?ZDh@57(l(n8h6-!iXTFZBPiq6*i9hJf6y48Ktzj6UB($}YJx@G&EjGBkMYVXvctXMS1_;?%R4PkRz~ ziJ8Cbw~N)5^UnxjD*0Hw%e>qO{cl8kIU&~XOgHBlshHJ>nt$9mJst-tzdJ_)G6wvlaALkSLCcpEH)t(v~O<vLwK` z%asP>(NK9Sl$P%|H#04}avA55VhDOZMhz!pWG2k@BtL06=VqXtu{k+i6Ho%$G;h~_SQ3k)bi!X&h zO_LXRs+fPfO zMR{GDx&ZJnef`5m{d}`rd@et~)Md?=w&v`|KQ0Ex7A4%aMU@$V6f`xQ;p^x2EJUFU z5Se-SdGmC0L3FhsNKlaHvTF`0^j&aiYWTA;&tpPrKRa}YHhd$%YMA#A8g&Y)aS8H= z`EFPath{VZ3A9-P3*kehMHpGp zgwW6UlEL~>OL)15{-CFMM0)P-NCDz@7M=0@_WMZbSEsJHK7Dcj6xoI@agVXgws_T} zKL+*85iUEucw4{=l-Z(jYmQ-T=#j5yuW0y8af3Y(VTFwTb5`Rtz(!qMD4Pb+1KpC( ziQHfgO-=a=7$p69aIk~{=ZcqJ>!jv}ea5pvGK>6@(66uhf=OfVyx}ZV>lS7K{zk1! zTulTE0>W)kwua_mf%pd4wQtju<>}A6p9(h%Q*NNb59s&uOOm-~=B;meq3w$ffDds^ zO&7|Swye}`9u`;?-*@pbcCpvDktv*5?9$*sf8AsAxX)Kn(*%K_DIe0ZeSDxg^e?UEy%yV>kpHD2nR zX0|UYA*x)zl?Mp^0MlAm#&q7bPnN+J8JSVubgpOq3EBz6w+x5`6Tl9aFAnG2x7=%` zBg1K|RK{qj^}W7CDo+P6XBGncP~ZWL=WXbQE>hIH*WZL{VS+7nU}4y*rOeu{Upoy! zw8m6>$o8Xg0laQh*r*~o((v22oLFCAh)S>s{oCkkvTE&EmQ9rjWrvB3$1`dHqtSJe zILN_(8Xsb#741~5)`nZI;e??-_BEdLi2%cBjXY+t%Q3%}X}IB6iNXvhJ^khK z^ONi{G zi?MWX-o5LuV>s7{6oR*XYwo2Fsd_Unam4#eS8C>TMqDD>$jdz=kS#)-Em!R|ebz3S z)SP*O5%#y(p)*XS*k5&2fFpei=RYuf0r!(hJ>nsIcT$ESTCwyo1ya{@Ufhq%{|9}^|Gp=c_PYFDXJJ}&1*Jbb_tAB9 zQO`S-;KbCE8jY8WN-e@})|zyM_DwjQBNrHr5}p%>B3RZrdcGXLiuZGG{QIpKo5AD( zu*<<9hoXQymB#bh%sSO-Q+aa1zZh4sFsVsKun@IOSCV>Zj|y$)BR=PPme92@#z%+>Oqg@l=D(3{q)_P%tO9w(%f^Gsf(3@$;9>9FhGxK3& zsyWJ~vLr{g=42%AKCk3yw7Z}n^E7vN+sAj-!-TC<{doe0PdF0<@RqV}jtWB;St!ua zlbQS-XOPb<*<|I|Ceso-!Bt0DCUc7bSL!6FQ&_MV;e7MRf>UMHR|Ea1ZS)9&M1Wx| zFV17*C1**1xoT7B>}k;FDuz*o>S<4s_wk&A6DdX+)D9lDmxlfr-YJKDA*2yjLIp6t zfwk81*v8OaM5uWqom>)Z$mnW}2=9W*5dc1?d2p>ZUBoQeDPQO+rP3I5wn%|Anm*l2$u zI)h02U!%1CAI?&U{=4M?_n*nBe?}oO6L>L(|0&!4#|!!w|Ck{96)jKrS5Lx!bcOeC z90UKCyZtZ5|M|hZuJ4{mG;9FP8MVKU3;VGJE%*;1pX;=PnEJT<0GHX|CLCTBka-RFNi7JyS=R3t^6^5Ah=dyms9qGMGu zOsZE-D4h_ez*4ocX`8Ywl$S96x|!+vBp4@Gtt|~OVEA}Y^{3WuN7`iDrFnkqNH2Y| z*a%=+aRg9DX6h{6V!IX0Rk7?4kShZj)svfe`rczcFlo)B>xo&!_t9Iq04#i--qsw0 zSi=JS)VH!x{tKnBjZw!IhWQ+Vgyjhi=Wj2ZYB$zbNO!{GKFhbCr^ZVFh8oU)pBBLH zjUM)Z+13szQrVBq$SJqlIE8NT)2Ch%b+j;qw&c^h_{Z$IHFWTEQl7ExJF@J9LHkK9zX! zq}7y+pYKP@@(TjO7L!jk%E!K8;Vgu|&+uG6<1I@R2bS%_8jrHowall%6Tw$HDde608WW8=q4l3H;GZ{Ya2D6ryPIG)-ZNzz>1pxi&I%mi*{JqtR11$deb{^9P8E3vMD&v7>B>8Qrd}GZQtkn6=(y0Y zjeE-}s;DD5GiX8pgcZw&+a*JVw**BechSG+!!i7F3O zo~C8sv5BcX!bw1O+ac}->|0W5LyzB?zRZx*_qx@Mb|eGLN#2e^Z_Z7_76lYEDix4-G0Y8T#PWZi&X znSTl1h5R4Py>(O^-<~fD=>&Iohd^)-PJ+`xgF6ZCPU8|JIDr5Gf@^}iHSQ4H8+Vt+ z(ggY4Ix}(YgKnu?<#uNuCILL5N_S)yZRSWuVHgl{pc9sxTr|# zF4srBD|a8KIvJ{J@ZJuJC1?0^H*9p|YaKa%Te!*j6JD7!nT;gs+?iYfM9iSG4af`X z0z&szw}`&u^Gk-k(H-al^Y3K znd*iW;tIQ~&TEQyAH2WlQbFz9f%QEeio3ZG?ffABI|u)SzIp!InZ)Gz40B@!OT#Cn zdKx2PJs&MTqnacac!ZU_D$ffN&>Dr!*HdexKLqR%b35^V-2xV(N)&w6J9zSMXa*9g zJ7IJHcO&L50bV80b)Aa~zL%xFnhN5565RVn^A-6p$mY|NFZZ6*0CWa49W23piWf8? z_b`Z9$T0I&M=g5H$Gtn~1f~wf)jM2er0f0+7BTJFjV-YS*=g=f-fb_p{ zb@{KQi~o&oHUD3}3i%&(oyBzOo~CA;t{Wy|9D9{ z3$F^!!Qu|Y^B1bQkjx99DUc{{BB-A%kdGWsY(~~g?h?OWs6&qK#SRZAd*v}7ne)|> z%pdzjM9;vaZf%?2@$3(Y@VMD2BctU(j%rl=wp^<>biLs(6Ukg$XSG{bu4CDtfU#tZ zPEC$-L(J7?`%yvmRwE4@vD$G~g7#bm(C@3iGs=*?o+^7gO zl^Lh{04e#}#_A3%F3zo{IEHULF#kRbkcEpIE|so=T-Uxp0UBG#PV*Vcw5yj>jS<}v7y=}b~VX3$IKd3VNyWr#hhnxSXhk{hxaT;lk zTr=Qn70j>NR1gQgCtH{1zCFK}%E@+$4H>UOgj_gM-NE;oUx{G`>N0 zwL16xle&N91f351ww_G2+=w<(N@p&ohg)1xdFpHye>859O)kIVVK&nB`?-t4bjPbn zah0txP`9sfT+z*ZnrF#@fkmrOc4}~CkvIDgOSB3+)dBBIEt?EM4$pTytzFP5?9Tp) zL^zJbUWI0Cw{4-~Mh%a-KiM$byeZK%>s2PHcl(BXOmEHl}PMMg9? zaj@ALtuMIWcOy|+f{%T#Gt7IU-2YAM+<1*oW&IQ7^e;eNpyvfRqPfNP!`m8pWX(XE zD653v#R=x%KPaPsAoFbHvf4}o7+h9_^-e>La_HH2A#Ejb@9U~$anz67YUmFXwF?|u zHTA2z1I!IG)8NOgU{c*5ew^36>zv@8Hzi zkU(S2GqMKRrq2`Zw%D=ni3!LapvE{bOV4V+%C;_TT_+ zm+DNQfNcDB-G6!zJ?xjZeuSkhG5)}~OV{_@0KMOhu4CBs$@yT{w$Zm;{3qm&1tPDh zzI&XT(m)Kg;qu9wD!BIqwl}9vBWeVw(U;F{H808bAh{fj^08u$;`nW^QEi{)u+myt z=niW@ItPT+up=X&V80(rE5o_yRXcSFznYq%ZM>^p1tVJIVNMp7ETGWAL^eI#in_Iq zfTwwQxhbx{(zD|j=h8#b`gyNE5xJq9w?9Pjn1EoYPJWDHoWb&a&iT0GOHzBmQBc~8H%SFkn8_r(Ts1b4by7C{o} zFkvq3fu7RQ-C(lE3tJ}C`ekE7lQ-0Jg+IjkN-aFhhDLnxdP8wbtK!7TD-p?Ef#?@= z6=wxMgwnk?^{gzwdfF#WA2ZgTUyjN(GNbceiJx|B3+J>hd4W!;qVM>7pBNC4TkM(G z&y4LZ$5*62f3$D@5Upehe%W+SNuG^Nz9rv_)|H6!kimgEpH2)P_yngMXkBaA+%7+M zJEZZTU|OKhGxSri9}Sp>(ejZp?CIYIi}$gX=OP8(ji4^xRb>U@K+*R5du8fVJ`9t z&+!6|x0|6da6HIIjZE+?m%zZZxRlS&H^l9+%1LYe0Ur3q;#J@HT9BE#jYq&oblGgN}`ivQ3wC&**k)b ztbxmhHPJq3j$iU&4 z@;G)G6+gXt6>ytOseHp|vOogP}D9ZEP#b>X>6pk8w6UVn; zS{-_H42HJMH_+P()~g#1Y{BMV%BAYlCHwKyCcd!#8rSlw7`TpnD8YRnEq>J#Wp7nL zncCzov}UHnFbbx(0_IL#z#pj~tmxPfJVSiicy^e@{59hXPn#XJ$y;#7}iQ*Tx|=Jg#mTW0g`bkV?q6$Qz=-_I?Weu!(B zNmdQrRHgW90L?kritW548C=7W!cc6MjZ%8&K5d7O?!9(BUc5b_~$&cuHLstqG9Zrk?DQ%X&AzXg_-P{S( zw){b|UhhGQ<%=Wn!w(z4UbAJEFXRrl4$u&@_e@EO z^X0o*B%FZ4{NK8=o?M(e8DPkcPAZkN^c&07A;9hxSc&>1DPfR&Yze5f#CMD*u9i%l zS@G>xCUTgiU{+1KFp~HsMjai?-m~ot9nj+5oI}N~jinp4Z(QL5{m*8{w>pPeCE3u@ zLR9U?mXe?epakKcvFRpZ18RL*0Yad>zfr(lT4?H#SA(2v*RLi4ml&32qXYw_v(6?U zEIJ4}Pd4IGs6g^IUC!`+xR&}oTuI6}A1v`~U8}D3s~l$P2lN94<=txroLs3DJEXJ! z%pd)q$}ayCFS!38g7d6>u1_fS(%9&=VxEro$H`Z*$q0;LxWYq>Z`Gr(QP4r-kM9*E zzm8P~2$BwBCqRJK5Mc21Ac7hVrT4i#<=ZTjO}1w-V0qP5h9r-6U6n2MfkEx$u`n5M z=kZ?uBU1K>eL%ULSQGqyx0zO|EPc0nKu1ZbsSzfWP*IKQd)Ip#w-Cr^BkCP_2Bi`F z?7`^GyHNQcVU3bkW@u1|1s5QhDbJiLLbklzN;Sg62TZk+6y|djQcyay5CQPWzCZ@} zM5MTI9uM3!f*Z<>Q|{TsYcS?9!5cGfAMm3(w2gwZ>`KT5i6I90#$?iWVL0ew-hjE{ ztTWFJ@M)shix&uD7#}%<{e^U@X`hy)2kYLK-g{lFzs+Da)+k8-`^$H#a@-0Y)NO!8 zsDilP;*Q867AKX8ttg%r7*pu|bFY-wF9AI-wS$}3PTE#?^DY+a$4)aDW((eR`oum1 zP&ST^#M?9yh=x)KF_f@qc(cWm+Ha7w)^>j0Wu@;2_N)&7I!~$(PunxY)>L&>*KmRI zuG@h84#}p+8gX7ntJd{sapBT~48g(3hAMnRqc$0_Vcf{w2uy?l*|*jqrYu=gh$5dG z^qC%RwO90=2`wyi1d^lLbTK!!{+R_j<4|5+Q4+7nW%~Y#oY(hlPx12z-4<#6ZS74{ zf4@=W8+qhysS1DahH11U@9cxh=CKr^(NUwWXj;6uT2TxcY(P=2J-ni?y4!6REbxkP zmGJE-%T~7eGW1zjKtsK6#$9I*P|AzAF?R0jpoMdOnd0*2wf-0+Cg)00nl1M*V>nRm z@UF;8pU#}g46o%mFL}2W>NKUC|5K2S8g^%&^#ztXhb_+cjJ)QSX0X0hJtTI(-cU(8 zW9xM=COh4T*bBx=OdiSLTT*EfWl(~soPWM1V$Y{OtUh@>svRpWWSbm z^U&jp%&6EAv-s3YKxsSD_2(}no2pFDa~OphYGs|{wkg`$p+Q_k1Ry6P*V346tnf%* z(J_py0ONWdhh(POWi3tiu*iWrZKzP;|E1X9D^msT9WBoNqWH%aXW({!RPK`PbbGzm z?F?6x^UrrRD-2wtdRuP4uACD`lq=uJy$JrZO?<^2)oJU<-_ya6+)I)A$%Py6(U3gX z4!4RbYNYs7%cOIV*)hjqjyY8GC9M0!w{W1W%%|na(joJh|HQp&h#)-ym_*_-k|}@% zK@PUf?=)Tj!i?srqJyc_7i1rv?>5yIEbTx8*_ceEH8I0qh<><4tiu(yCb}|lsSt0u zNx)ldyBD~h#oy;2d3!Yu2bGxE#1V+QeP&c-iBPK_nA*b|(dZ?`5=sS~p+8`5g0swT zmda&}hdJDb?+5XR1?V{3p!CqDFV9MKEjf62AY^wm_kHVxP_c_3Jw#C+pcdWQJ`u?@ zb0gNq>8IS(C`{p5qu)SQ@i7!enmFt*Q4`{z_!IfQYYy6Vp9w0q-?^uabFnie@mDGD zXrBKI3Fm>@+OnuR0wv4Yb4*pB!;0m#iE-n69Fk^Sb^SOMiCo_zZrN@0-i?Z?WjxGJ z1Y?jdmC6(KIUsn~or{xLD%cIc;q9cZ7N2Au*pSy8iT}+uD+mgcP;m)brbu|Wl}h{@ zME+bT8W1RK6r{a738Dw+CTrUbE~fwRd4j<|?qG(s5c^;S|AgS*(2afYl-S+pwqwq`A$4gQ?_C9nGlLQ($eigiH?bUbW|20Ol3#$FC=zH%EmL5L3YrQaejwZ=55VI0ayMXlQ_Rp z=8njcV-klrg5o^MTy^F!j$f!S!m&t*1M*&#gbProv|{h`w}%(^c6Z{53tt=^^}qQ2 zd7Dp;b8JP(r41Er(h#~xN=j$>>y?a;o#7-wmtPQyQkkYj4~Q&Oco&oMV;u#u{dXxZ+>N1$-O zKm`4ofxhvqTso4p{KeEO6vMr=i?7JXB)ybE4f%qE^vni`(yAC}&$xHk_rYo~Vdd6o zaglOt02$Hu-hQ%BgDBPFshcpZhwWEH5Z#>}^r4r|J+v!;bf^EZ{~;2gJ3*l~po0j% z5bj$i5a)6{*{PqY+HLSNTogp6x-hH@-V+bYU_)7Aa82=~+xc6)lXf`rKIRVNj|AlyP)+nVfL;p{{4OxL58a0A#+0%73BY ze-p-&0z<#4$(au6?yH4JGCi087JuuX)~O$qwhgOD2DeQS@|+EETz{s=1+C$ja*lgT zO7=v!RA1CYMRc!-3v`V0KAV-J9<&ZpeE%675L^}N0Lb9J*L=)V5=$Ml7n>+O*71A4WB0bzzK5YNYd-h{V4!CoeKotq1 zpzn!g-iiC#QPMVl{(96=a&f{H4^Xn?S$;b){^l-SdJri?MGv?9kM4*G7aTR=iNW7v z_6ZYV*f)cqRlXPqFFDpto98i{C^c32v9cnA#Y@?|7tP9GsK7_dnYA>FB3Ts!kvQFzqsX^}y?gvH_>iYQxV=vgi#64Iu>GsTqb34i^-q1#y1SaF6^GvVR zf%i%-_@1IuNL&VQMjnn(DTRjDecB-Vjn05x5de*w6r$Obh#M3 zY*Gwc0PT7*6ShSInBPo>PQgGN|Br~GEl1~`NENtz+17A_gnOUR8eMJcv?iz2yXh0= z_IS4Z_V_hoea2KV$drNpyS#6wudUyI#hotyT@`ZL!Sx{9`WSqT8*^#zon6v;T!OVua9j$k;c^eXOY>3SA#EPcPuINyPTNOOn3?9HiLNB|(m0MR^#eWmO+3{WIG7*}8Vu6U7h8r+G zNW+ElJGlMs+YV0zmNDC<%XKh0TokapEM?j0ISkDMgIiFETBPs)v^YOsHql3@DL2gu zQmz{8I!?CF7ZACuDeGB#z`f4rByKxowKe!vi`~ zFnOKsArOi=EGtYxkTpgS< zNQBFgMYtn~gys)Xu z%o54998BY^FL6^wxs>MmC2yafa2t9dP$Pif{X?j_HQ82biD5*hG@!;Y{7{X_;>EoP z0kAt;w^(!D3c8@_(tVdC(`9D=-tRs>mb9NXXMe(HeoZeO;}WGQZ#a^3J`dDa7l-

$CBnn!gDSr9bo)Ip92 zd@==atD37OMhFUb_mVNrUIBnno;n0Q;oT?18pk;+_YT;=hUkV#*|s^p?;$X;pO0N* zXq$b|wf$&b+|4}NUJ`MGUY>n8N%eV_LtdT<`|^c}B9VT`dezD5#gFSpVWp0l-OidB zfiY_ZMJ{Wfk4d8@DJ&h)+TxP8abC$I$l-&6%l=Go)spRm@HKpRYHfAJQ%m8J$qJ^6 zEQ8@^9R>UdrqkhVrtg~Gpkycldov6CCi3l^XO`3biLRG-qwsq>&4$(3TainHHH|nZ zL9G+^-Vb)J3q{Fwxvq;*+@<}^wd_{Nn;?;y2F~|7@)=J))Mq!JnVZ^dsWaWnm?j#O zU}2%Tjz)f2q@aNg3V+NC-JY^iz{Y|3y6#Qk(t&Hk>dZKyTD7&kO^PZJ*~0)OynS%p zijLyefD$y?01))DN#VLN^%JC!cyNWh3dP2nzW$idv6x?RQ_|$GFCXb+`G$(T9mJy8 z+cIt_xKP9N11BWWYA(Xokm9ejgK)?=D;&#dp5#Nv*8m|LvWh`%E!LlyB=jgq{fk=-FmA#R6H5Fcn&q6UNS1s?=DrXEa-j$?u< z)V3=m>ML}fp8nWp9&%u$+zY%HBgA5K=TQu;+_N6oQt^8f3)wfpM>v1n#Pll@m=`p* zf}Ifs_y07J*kZE5*aRg2n%U0kDE3ppsW@L$Z7O^U#6n2Yf*?3Bu<cdUYbgL-RzSJf)&}HpBG^R#!2Yly%*jmE$x-vdk zWCEdJ2DFK){^%-5Q(4DAG4mn&U4J@z&+(#|rv*nvPPoF{$O>(^hzi0zy5EPoC@?m7 zc_8oBJ}_R4t;f_SklVdCUSEX-%1CCu=v%XF_tQcD2@juOYG6VkSy2Mj=V@TSHx3=gkfpvw`DO9Ty&;vkAfcsL5YbXzZ513F@uo=%qvq23C7?9a*zH&BMQ+C^hRHhmLL?l$6-Jiq!? zD6`&VeONc;E!y_+f@QUpmr1m~wp1C<%R*xvWU6{8c?it@UV-(ctFBh|gBhEvBOPxF zk{>~3-F&9XmiBQPztW=Eh5Uz#KPFRR;RtPmX!e17p7Z6c3nD1*nB>nun(NOlSinG; z=f`J9{Eyiq#ujZRWQ^ma?nA%Qhhx9XYX=(qhH;^0BKSA0!=Z#U9S*7X_f%^CW}V*mqPx;W+4_~P z7%v^7yA@ICzhSSHm9^+6-x_%K6(vU$XHjd&pHzSf}NBL?A9O5sf)5=R7H$pZCyDRy1JC`;{3Bl$*Q- zKgaR!6n!0~xNB)G$3YY~mQ%pCf{O)6&3hnp#6cwwq6zP8P6S#wUxpr9nwQ4Jh=sSt zdqMv~GP+Dp6szN1PsL5_qjd*g?^fPVGvX<1+>>BNNelW?3 z7m;HI8*$ytvuz|I|=k!h(*oz1IhEOp4HUZE@+M z_zf(K;YT@j>mh>d&e-27J?*J=d%P|U^z3f`6ipxHulbYbXP>SXHY<^_xBfCB)%JJN zW?W@$rs2$gc!u!IHMAl5;lydLyu#oTp zp-PG3n2A^8ypqr&9wb1r7=F5rvM4rxStfX=SRDw zyLlQJY>hCbsn|jn=jQzG#k-_bwj#RRPZYyph5FLpDfW|n#0sj6={sP(PICSPqsiOI zA%KATC>pCOZ6#kdrjDPVE?lbcb&Jchk&r`dezS>JiR`$WG|6>ca+5reUUbIn0O0De z+mhl{h=`?%Xn^D&u)c;>nDpjIP&qc)02zL^??!@g{>Dc{kOBotf_*{7?iixMIMi?W z-ERUnRg1*S!R(R-2hIPaKV60LSP;m1w2mf8Ew?pBdZOeiSyNyeVJzd*7%HLpL@Au1 z5?g}LQS@|iI81F@wQMA2KbB{c<|}Wq(8tjj<6&8?PxVkL zKAV_M4tl#I@;91^Hl#8HezmzC-Owh1+N=BCPM1^&&(5u$Co45Ija$HV*iG*fjmes} zICT-uiEC1qpSJ&v^}XuDtBz{X@4C9SjuO#!jjFdvbh94&*umaQOy)a~zX*aOT3UNkjSXKyJrkPDoj%0}Q*WZhSUIBxG^ zVI-je716VXZCxp9e{{1ox*QGrHe>FdnqRQWBF^#{bF146&b}HYkvs1}O6+Afkbn9b z#*~>vYKInl|CG_ua#MH?O6+v(YX4(N@5pUke@yh?c411O#?)xppeAL*jQEW_GT7>E zbUe_zK5D%i>@lSRbkrV{HfhlXTp*E81QG-RX2%p1P?+H$(bOR2+rAp!YB#+zW=gw< zdd44FO6Dtd(w~p;Ju-IgU8C=q5p0|z)s8+| zW7pe`Fs)|E;!tv6xO~Ug6OvA@bS3Gs)bAS~zRgWwXE2|ayM8d)?OJHuPd(G`-NDq* z+{CZIml}u3W5(z~_wgKsF`BDun=8nA3?qna5RUCx@s^vg*T>u|Bh-hT*HH0A{rt3J zEJx~Z*Buo??7YuO5=jiAwF}!3t2%z1sw0aAh7w^(YX++V^Kh6Qt^n_l@n$SP$J7hQ zbd^dnk!~V86za&6w#`$#MI(rJpFwfDpQY=TurPk6myaV<1LAz{m~Ii3Y&TZlvk9Pi zP_|Q7iyYw#+MUyK{b}Jq9X^W7vbC1LCkfV*hTreZU(R|qDxirOS6b9(9;{;?EeKi? z$KDj9MMm(;T&SjVB*SckbZ&Wug|OnN>puu`*CRKFj3bes8mXN3wH>QrEkTkN)EZ|` zZ}9D%9hockKBPXK9T*gfWeZxyfl<6ISDM+YtGhW+tInv=tFj*yw$}*&5iDMn3d6EC zTg4c2XAyfJZYQ9C%eg!TnJtwxTj>wfp1^Wd?h3#(5i58A&sO>yl748 zX`bxVjGx4HC+=Gu^i8Pb-x?}P3*iTy#Lzce)Lt{a89|ZT;ID@BvrMVy_=eP? zCkDT2Qex|ihSy0k(1rpc0eZnI`yMgkW=m*Fw-2=!pYz95S|66=Y8nastrCrRc|ZXo zC2*696eV6=GP??6;fZ7Yu!Fw!;wB}lXgCRmfPtw;YYbz=f}|{mF1_T*ti!!MyGE|M zM^IaLJgPD{179AuYDa{W+uv5X|Fkn8{+qtKh%9!|nXhGHl^XKJbef?R()n2s)y@QMK;sHc0{;R z6j6{jYV9U)s(IHJzK#8u$)SlX@tAU|ih*Yfq}A$!;1 zJ~ZE>E!{g}#rs@m_ZufwuHOx$F=TrkZ?qDz)KDgusR+p6pPou~F}F2arcR@G&MA=S z5wbaix*o;@)SIa<-*sb;n*!O?qD?SbKk21nqiV+AlFpE<;sKRzD}Igzg4cY`v6ZuO ztOf4QILlrnprzwv;ntm2!-*eDl{s89UzMQK<;?VfW~5@t*fXK7<7~+Dy5Aoge?R$k zK3>~^rpm?xm;HdGXZ`7q0P?}yKCNRrkoBAcT2>TD*S=Rdjcb1)O#tr49dSs$fBpUS!tfoB-riK2bJ!+>KpeH z&+#83(Sc6qBB2^92d9REZD9t2R>#5^XDY8F^)j&Nk92Ttr6E?=N8GQtCC6P{PrOHe z0%jnAzhyKkg^Dx$ZLw-s42hD4)}zu3!bZbmi7fGxJM)&WGf)fWmFpmrr4F{xS<+``oj-bvWeVXp@>qO*vZ|30I z8}#8bA1~P%H1n*j@uY86yXiZovQmFDGuMhMCjw21wK5>Pi~h6PUyJypHMw1Vac@s(v$wGtnJ%9Bqr87~ zfbc`lW&TI*X4FySPjbP(IbyduTuft{SZT{$u^nB2YctKw)$Vv+1%d;3O8zGGEf?j;2ul?$q=43dnKVp3i1~$1rDD{Kmr6c8 zQ|xcWVn@EFk#{xWzu51GrB+bdQ%o#dsS&NIxfkazi!H+rr?%K#rt=+T_+DmvH@dSR zcOhXTpIrYZ!98ePlGR^uT9WO6#Dr%4%&MWOX3nGC*Z?~-!;$5Zeep|E*|T`~tL6da zBxKYtrd!1gr3VHkk)9>Sf+abXha@wi+t}Fs)3OKPXFQvYf35}vCTZMDpT=m2S_nDg zD}1b}C{D8Jr#I1^1v}C`JuzjxiFk%78JCUjk`&>}R2=aWa?; zykk6R^tu!~^-TUfe=*3Qz!S9APp-FYLk1GreA$KwaVnSh`s*u7;mn-1}*5<){u29e)3NP4ojo_4HnyZd6Wh2BsMd1!$a zV$wIDISD&Ve3gILc1LosHLc4|w%%HHrn2i`nZ0o|p~WwW%G$dZWlFOxXpGr)h-Sh> zOfWnN5K?M!(kX>i!V0ZGul7z~pe zh;d2P^=@hn%x-ck^=Ken&{(eDRU7FC?aKHU)wIPBLS%}3NYP{4A#$;k5is$YD?dt)GfY=K7(TFsA*hA* zg~ki_^{3WXf}oW^+6Ts|hZkE3_=ujhTX2P1-;;D3!)wPp=el$ZMYAToE!#y!9i`}V zPc5C-a-iYsG50}OPJ-aKdd&6@M_Ysa_BQZQilC4Eg@rElN5+Z%-Q*(hH9jR5XbnlaQ%spcqV`@W3s~ibYd$&UvilZ)>g(~r? z;k!JhUM|(z<-5)_fNeq)W4=4AO4k1_Vx>notbt6Uyg z_uqHX;KV3(PHsL|aS@Gf=- ziebOz?VOoXSbRV{YloO!MYDM2&z(j?0U^n8w1I!KySqO*!dxh-6ykI&9eVz5j^pDD zm*W}cc+z5@-k^hQ?0SpJSPkk(ZXyc1!o4BjAC$d+NxP}KVUpZMgBKv9HMc#Jw5~p1 z&=7sOhXUbZ0aLGAq3De?Up5J?;KybZJXVwf(VqJq?nVBF>N<`%!7X;NWNMtvEf8$l z#0+T-?%mxDoZn>IUWre1w(YHEeEQ#`$aPf%)fgzbU>j`pu*{>@u)QpOC&}8zBJthG z1S3Cz1#*)$UGST&GQffjK(nj>XcpFHWQ6I)M`z+T+ZLWx!GpB%v{RJb?aK`LoS=;U zg2!d24;cO>yIYw*<+j=H6^kbu^aO5%&MKHDqg)x4)04?TynVE0QfzLR7Fa|t*d(zZ z_>xAJRYjkpTiaXHWGB*l#GEA7K=LefFb*jRK4RhYsIFKnq^|)YRqt}ppt@U9SV!|S z;Ntd^467Be(TyQ06QSIj;i6m9yTqVK!h|cG`TJ%E7k-C~V zx6*d6?6BC3kRzB>s6S_}5*AD{i@H4V4RbADDhETVny9oAQ_`jX$sotrut*i(oWIQ0 znAkvuSa+q2xAo8Q8EQT;Pjr+xsu$U3`U&ScZ@5;3yo5H%-nwlfuO~#Tp-=?fDo)dr zg@2v0$#^kr(@@`7uba(EKL*2_s#l@n+d;=i9%4(bPt^fUaXyhE zaMr;I@+vICbrDnLnj$nxUdsY8++T|p6Mr5Rxda+vH+NOhT-?^cO%0+K-nK2oXO#{X zf-9gi`qEbB-mVOb%PM4)L~=xs=A{U4DRw%lHsmu3=U^yv;i#jlWl3rF{2sV3eRVhO zl&{as$3Vf#+8uu>_2q6C8Iq1vNFd{(B+rz9Upkecoo`%t(N5!{zr52&EFxYq#+UK# z(JDOLIT247LYlVgOLm+^@vmdecVPK!8C!gxyoZk2>mrSK9H=gMwT^`EUN;Apw6ljW zp9AR7=XN@`jj)LCPT?6V@^Ktj;t^s{pMy)%bp~*-F;xm+1^Ytbv7j_)qW8(e2q*q` z&l=6FKdJpgq^`eK*N*{WfY7^IoM*o{Qtb}l>H9_#bg8E-bIgt+s&4iu3rf5pVjmez#mj-PF zN59iJjQD&ksbh;W_;T1{lM1~`rRqI#?+`)bSzQMLe<7hmf|TZ+Jx_%u4NZ>N2#f?A zj*`%{7zk;+oX~!@g`UBX#*v680EEX8?bXF!NLlP5HDwU?-i*CE^DS)EH6`ck-d31g zbA}XaHoCR~W-35Cy~4p!AWr!EbZtGo;>KsQ`gKR<ND)*Jv@YM`d`d0z6i9oOi&JtBQoDA(KUm=W z*Fk3gLNc>`iu+s6y4(3L7Z@y>bAl~3)p=fERCODl2cUCt?X!L04P`W`01ZN>#{^dZQWzOexhGl&OJZp;VWS18yhm= zHZow`CBDcZ`x29sd)8~N9sI}n?-!HV*{5?+bRG#6+=8&!-bk^mR+co^U&US)R9i=o zXzH@cw9;tMFUBb8b=Bstsgg?mEmKe!VQ5lIh11S(c zDj|O%_5TTz#9t67niiBGE}8t`!je)PZzbc$8*e;8^mAmYCr?psWh||S1T?>gFy0{V zWw)8)aI-xu60k95v}djT81+Su4S(l^$?08Ip~V7fp1moaAU1n{V=GOab6E_!4z`$X zdy{tTuhPJIEU$YKize6b<$8XnxJ*{PYOz#={)W5)cJb4#VNRn&SGKv^0*zu5UuN)= ztyLJ>;@RC-vmMu7n2&l*4dm7>D;r2vJ24z}?Fr^X@m1dl8_lgjBiLm1XsN)kF!`o;#fJ@a6+tq3UweRC96GN>(GTyToUuo=^8sM4AH%1kp= z`0rqU>K_PQ%?tU0!fyB6qhpVzR86h}Yr_RwF3^u7ChHGtI}4`D8*ai+po@sovR6K+46R38sF=dNL8vR7RhhQ*NmCZGUyWAK)0xfA zl9ZWn8TgUlvE@^>Y;R53Lt=Gvr(9n9JW)aT zu6kf4p$*hx_cAi`+ez%phQpSvO55pPqP*!Vr{>*ATW!%uRrdDImX5?(g&$byVX3dnLYQf^jkU4OJ+gNQD8? z2FDXA1ZPk+M>$4GA@pc(?eZi4ut4pKfv7lv5=ZQ`NYoc)%lH+f*OgB(A)}DY?m!B7 zte4UjyHo?UP*8*6>m4j>Y(MuHIwdpxvs7HiO4|AskIRmG397Bf%_<@ zP5-*)mJEKZWd0hCO96}GTjs{^py*TE6&xKv21Sy1cDEz@FC^7?>)GsS!zB0nB@QEr zHX+=#xL~@Q4N&3>Pp#lh&zy)g?1hFwI9I`keXS(2itH`QsMFQW@bqo@OAD25{l(Z% zaf9=1KasXfdzyR;yU5ZpbWp!PRNp0!|*DtFmk7Ki0sC-yI zNplphT>%SrG7j_oI;V?udM({8uQZ@)KY7qh)|wXSp<*%;Af{0l@8_2i$E3;I{((M` zm+Yl2IThScD|mSNT7q5Peqs7Fb+v&qvaOjtXH9ieyHI3;iIq0oUL7?};lg?oYG64K zouTwJ(W+kMBG8CUUz zXYYd1IN9rvyEgFHYjbh9`=oH8%v)LV>$>yh8HUGt7ERHR{fsra2pwIIRm{9s`b3F- zA;v|d&oJ#F6`b3RVfa+ar7g_yL}nH>Opi)qYX1+I_Wwf?I_2$kr0T7phE=b#oegUV zDU8jBAo%<4b!=LN$o}^$On)BxQX6?-Fe8&O@hRDv)^e{yMmPmOVXPU&-}H}#g8uF) z3200i0)oa5QrpHT3w>*(?J6=V?N}c&#DkT28>(s(xwYe&t9E-S>2X)WrQ#V5c@X(cz>NlXy`Rp;<96f&{JkX>w4O2x? zyxYjq)Eie&P!A{teaqbJ$nxAYTt_vrGx&N-5p40beL3B~L?w=3I9P`dYVI1}r<-p9 zH2>=~5ptVZM#!ZT0YdjgGcTp=zXZ-$#ZT<~B1P`zcq7iMsr&k+WHFiq0Ch06yeN1( z163=9RF2MX%D1&>1$c!fU`rC>H+|r+VXJ{XE6D=6F8C~haRX65n)M3( zhSfahU7CDc{;U&YDy+v!hi6$amWH}bT33@=8c7&L(=XR`B_ z_mR_k#fEBpMx9f8^@gP_gX;yQiqOEo$g)~p2z_InEZ~`I&Zsvqiy`&`^sGu9mBn9# zOX+Ix<$ZDM2-42Kc#&2;UIq>Pn{B|GbU|O5D(8VQ3CK8I|3*eTW(5Hxs=s@b8e1Z{ z1^uhr=sz6$AAgr8(5ndgb2G1w`to0=8!(y5b8*!Ex7VrXSLES;aV<5y2hK6>AKn1^ z0ad{G?zf`s1`~V33`0fADa#9jlj^A1G8er))xd;Z9;N!FvuC)|V7ppAeQCivEZU{o zbyB``nra1dCkVjF>biX0fdQdm#~kC#Z^@Y7>%VT^PCC*hY2@RvYHA$*rKnu#I!>(n zS{t+gOao7!i@{#qC%Pc~m4Jd%f>qeMxV;z$r@K`sYvC)=O(e~hMc>oaF<(yhko}DF zUR-qhPA9J>KlB?+^!kPD9-Z1|#g`&MuWW>dDYK^;QK&zQFXYWM)A-~)h|D}luegQ^)Z7uWf{Hnl|#vB?B`0G$$h!viV@z5b(8h>o(Py-~Y>y~>J)KjUoI+u!b-nBPG$i*{fLXvF0c=7SD-of_6nRYbHBt9ey z1RJRI1e4TpHDqy(JdJ|eS`;g980i|L;%VL!oCkdBnA^EmN6BK@l*Uy0^3Q+&CpoD9 z=nDSjU+|wOM*TNct3+uNa&W|*;h_E?Y|9I$5}(}4xY8qj1(98no?aMdC)w4EM;>cjd)GbNp%% z@IoVmLT@%lj(kVGqZ8(GOeQ%o_FfK67HG`lrL5HooUdF?z0r69m1@chHOvr!xy6-I z_A>f`d(#;F?qV&c;-F~?;;}Bh;9%C&+|=0|8&H%BTl0|ZvwS8)s1$d?f8!nY;P$_& zJI|n|-ffM8G%-MwUW5pUASF~mDM3`ah=BB_(utvWLX+Ml3JB7q_Zo^c>Aknmd#|B~ zBLBP3mpgOrhjZrKIdkUTnf)PqlF7X9hrRZ@p0(ERnO={D=kLUQ0bJm1?@S6b2CYFO zHVw7JqVc+Y9WvNIzbjq$g}ueWv9`-J8&OEUe5Cwn3EPO%@d{5jVs$K{G^_utfqeh# zhWz~irQsQ3!6YF{UXI_VbHmBiUpe8-HL)pGK`)x{Pnm)VfmvG_o7kkg5k92^RO>Poeh%0>^MEZde{^1rR#zEGm9i%sv4VGYNt zAE|+e0aSU5NayIOvzZn~@}MlKzwoX(5}|p_aTy$$8v43=@T%(a{M%-3DEgm~(_Ggb z@6$Nvn@Wmy>kXH@#`$uTzjOQw$qaLCwQ1(Cj~cEZ^4b6D?=RbQ0Xt}!XOCYQ z45^p0$W;~#5IHrb9|&4jAGVIyLQTq>RWo@Hbci-gGKJbHErwkZwEcxgQ_s9~TB`3k z1HYQn@)CVow46W~O`9byL)|)V*WP&^`)1mD5lI4|p%2=B(;ykKXBCS(Dyp(^=gs1; z#lK<1mK9HD21VyBEECqvwXekcQa+_Wf?5A;Vlb`;0OU;ShwMhiJ|Eh%-Mm|l)zGLj z_@+PCs5xqGRUoh>L&P+qhE;)+nd??b(_eVx)+|iev+Vd7Yb^nzZAt@uoo!{yRFjZS zM*6)Kw7b?*hS<#8Bf`Yyl8-f+gRgmi2k&Gy*3LgDQ-M7r;}cANLHdHhg;L=njJ(O2 zr>iUPz3Y>fS)>Zi%SxmQ!@^n~Wl4>WNr?AY(hT9jxL`D@8JbDx)0KoN@%Ea}geX5gmGO_LmIZ2?Z;PS)A@c-@JUbz$S5&kK{tke+qf#2=!z(OmM_t2H zm%S+GK>k2NX?0K1b#Z3LskU-rcQs6rGgRkIQun7I#ds9O<`C_NDR)W7=gemAh9zxn z6Oty5OQ{r-&L(%e!pVY1O^`TMx2X_RUysP^MD<6(x?2!!fvTX!R${p{# z8EE>O_z#+$+{Z)|7FY7$-tq7XW3aI)wD}l{k5^IuI$y|*;UR^!Ev5DOwCH!6lYSwD z(N<;@*WMC$COU%7u@0HXXyI5kKz;v~9q2hSr|?=57qQ3DRNG9ytC{s;8tcN83gld*9+dLs5`Zm#HT&qa3b@x^Kt zz75Fq&F=@@oYGoi?SI5QQ;FoWtmrURDZ)-5Cw7IO<=UTh;|GNVIJ!eR*E*Q})_jc< zqs&Qq0sEc5@IvE--6mSw%iZGm$VNb*&xiba<({xqCRP{W5fDmSz2h zJB~7i|CnW7%X&F>>g5E8%t%0K z=wB8g1u@qui%zwM1R4{3vpN@AMYdKB`GChY?V!tMFw&<%$Mj3k`(`}ef>YzRXb3ns zk=kSMOlrNnUqtPD5e;6HSPZ3N7E11&!ZLZyk*;qGk0=q3-=P_%l|SNgEj2vbm|SJ) z{E#K;K@GaRQ7~xCWDKQpIO~;{8PhmmP&B~$vBogtPQh79!^-&3wFMw^kT5^m-?(zo zWfRNKkE_}(?G-8z{$e=$YEq{au{|ThfNVmhBCsYMdL&T?NadWZbC(HmpGX!@5=MU! zdw_&T(pw`N((OlJO*Gje^T zzY27eudV9LhQ8RlaJ%$S4ZnQS7??d5E*h;hc1kLei|*zKdn`MLj)>TN~;%qxITZ(m^hIt)5JC2CsV9Qq=BnG;4%#Lf_r)ez37-&g#ocQi%CxgjD_o zxRlyv!}XZkqY?n0b1Q_$epVLHK?P-wthtzYq>yT|ihADT+oSki%BbF_RhqW&)P3)( zQ8^=-cya`ARm`?*JwYEmRIJZybBK=fJm#A+3$ny_6PM6D zFURaDYu;@w{Q_fQ?@jL`xpf9Y8^u}eFF(JbnmpFrgIjGw9IjuLBFyIp<`>??+*?HP zY!iOskpK>xXi^u3g5y-V-1ccn=6CGh4BIN&?=^pw!w~t6Y6waEAM5&Fg#Vy z6nK9pM%MRqdfA)Bt^BIvhN|pP_9g}z9%#RHx9%Td{>j_2r5QHl3F^3!h}HOTAnq&XUSb&CuPc6WNo{{Z(W9 zjL~XsxbnWTS5DXN!qJ3Jf`MHwjmu%;r7IgS7oi0KRVMQ+^M_tLn&m$qvex=21s#FA zIF;4aNR(u`P-MTVu}tG29=Rjd=W4$y@H3I_83cfzt7^YT4c*xLrKC@iE&r2F<;wnSbmL+ z+}yN)n3Z~T)|Ev?OW2$FDt_`a7(W@0{T58{%sKXg^mKNg+_MtOgKss4cBL;Ohi$PY?V_Uoa_F&Ly$;Vgg10p& zg@?kSPR^C`VFL8fZrU;GkB$r<1zPDZjiTPeT+47o8TvTYwnWpIsYi7shSn9p_=&tV zX!m!$XYR@u!P)J!bcH%!yBvBFg3T}}iN8-v@gZ@+3P_p>_j$b=x-`bSZ!|wIW{Ld4 zqyL=>4kJxSS*$w3d-vA=p$+U9P(WC*#hbXG83WY%TwrzBqeDE6d;H~w&kA1QOX{UT&6~@deZJ_-8_1scEk>hQC-ON3jF0Fnq z33&k)Iykn|P(Ng`wxRlprX=K`GB@$bmp4NToenIbgFVI3_D7`;@7DXOcxK&iLiWH& z-NJU{N6=m`ZkpM#XYmv<<{$i;QmB7bC9Ec^-ci!aFNDXE^|i$WLR8fHNaCh&5{4r{ zIhW5w6;7ItIfz`+UG^Fd99^!IiG9kE8A2zuA|Wq{$ph3Q;Wh|`q%6=FVkw@TUMpLD z_M|;_%(bdiDKUU;0p1U%4p`|<_?BVnw*+68 zQ;K~v_uHtfcQ=i83Ik=d9U*%HNb#_LLAtu^8<2x9FQ^rnTEd?cA(l_ewFnp+TFz&OOIAqhw z`Li3*hplQC{{b#Y_A4igZ>01h(WuoB7Q&qBAD*!ux3Nqx;PF_}X zcBSfzX$748Xc$xzO}ZkZH0gu57eCod1d#Y`{mnHy&Bx3-g&6^DeLIRMJ~_7W9)5z3 zI~RJmY#swBQKN-DhP_nl`-nEdS*fGsChXJ=lUum*a6Ne%&S81PO_IZ&d2D3fJ)EO2 zl&lO!_&ncMm~QYXJAHH4IX9FfW&y{fkCC*<+R^(yT2$zy-)+kpH^E6adhtc_)?>pO z&9;DFga_00P#(de`Ua^h@duPPk(`5+dbr=3-g#@M z@|?6W)+rQ`zl9kw+N*On`@Aw3x|k^1D=Z)D)${g)u6&Q2tVa>4-?3(Avx+fkp754l zN1nTFe!Kgh4C}#9B?WIdWA?@DOE)PBX#IBd(Qj-Va!*IazSHoH%Z2@M~mVFcXd zRezPmvkE)7ri}YPU02FULlxuLznv>;EwlzI0T!w=< z39MzA_9MCm2>Mw&u8Ep7)r>H}m|qcH6N@MsQ-ajZ>&*}?ay7HHke({aiUOTSnYq-~ zs<&N)glQ2H)i?BkN*{oofr+$%_$BEOX>95Kwf6F3blnx@(aVqd)u1Pl{#<{id1xcE zV=zwT*L6X6@$!XtfiO*t9c)2klLzXS$sY~Aj@Fy72)w5?mx1j{IaZkROEC8yKYd3+ z|8af`*fWBznT3D!`lag%38PeY&XcUl&#hKuc{bQi=^wlmEDWhuAMUK&Lpk)(W6(pB zEX-zD_j-wCJ_#f2M1_aR==-s=>3IXmVMY5~1=PM{WII_{-vt1H_wNAL4BJUkwHT4% z%F?YE18TFgG6t6opEpZ&WZV}ci+Ai;kW?XydM$cmWD?5m@NrQdbV7qvQAz8tTMFD_4>W=zENivxUjK zZhnY~bG{nActI0ssALmUj`2w4=BHa>|3u#N`D^??(4fWor!Z}JwH(_&UsQtg7_vHA zFo>jU7j7tyFC?t`l<_)Puop}zx5fcFhH!mh@UE<_sA!O3UVSW{M@EoqNAL9X!LiYi z#g_a=Nual|N)|3d`_QH$-vB4vS_P#0BGPyDEVU<4hN@Of;jKa;FG+La#?l$8kh{z@ zXV;lG0lgMxlIiY0qZDrm5t|ZKiD`B-H1CV6*}?7%0U5P1)3)}po4y8S7wxGa`Nk;$ zDdUR3zo*|AmH16znIUD^9Ho6U-WMnuS#$h`XP;S#pJI!VZ>}SQyq?i4iBIGz!}u{< zpfaslhd`P|4z(fvAuRQfT?2^nQtBN{IQHRsjRKta^nvkFTU-&(mS0+xLhC({@l#Uj zf!FV2=pSiEKq}FDFI%U_s$DKUW$n&7z>?ff{EWS{4$m$abex;mv&j7}oDx$by&*`> zA6IghJNj7FsOxtoRWYF`1V{_Uan%0Hxmi?9r-gQ%)FHE6p#ZXdK2?NFW$#htO4^$i z-FP-2?!2)hF90ESD>?gi2u)qKr7j6{wtPYk?NvB*8s_K^dycTZepbpwFnByKaPzUt zERxnZc9|7+KIgA8`U=&Jh#ZFk(`Ru;qba)z!W*jDhG{jE)l#IWe_~8Z5 z+-3nq=`=QdfPcT%c8f!G=qTJ6$J9CT3h5lOHq9BkGD!$0wFJA&Ui&Afx>noFC+F5c zIIrn()ra6t7Ew{XlUjA%?mwl~dTup={3jQ@wuGWxaoc+48noU+qlngTf}f*1NB5k6 z>cZ`HA>4eb>QRc+gl(u!;-S^j`+>6!s@`0UzBcNnPI>rnx;DTd8Of8WTH^NkNP-zQ zW1Aq7bGvSmZKFi%0a)FVz`DlMHWWrwJ5niS&1W;IXIaKjlDzPtGW1=UdrWCpoy@Zb zxA5C(32KU|6mhYOkq+C_y|2ejQ1EWaT+P@Oq2F;Md#Zxk_DADC2ue9CX$k5I>%1(K zYsaA{aL;e3vvxL=+qbn9#dCMFV8oR^LOqx6+o&Xk)TEYJy z39T%K&qL5?_}VC;UQFH9{iElg3(%Q8`>UP>pIC;gmIjxGhl9m1vFMk$qMS`FW$N0x zKXuC3(}7YmE9fJ5iMUMO?cs-Vx@4Y`lZ#w;z;ltakaFNSw*sNDG~%zv_TPNQvZW3SA2~+|3$@)TGsK%2WP;TK7W=z*yZ{ zXtSzpPM-OzO0K-et&8G*>a<3?mznQHNx2pmF+)JNOJ}u<@x4=!*E1W8`cNTJV4G;r z08j4}d!uqTsY92!u0~(5Nn5s^ebOE%xGGjd|$0` z_S-9pBPG1|0vx|KE2NNF$_br(fJZV6oJEchs}Q<_6A;3?XF;QM{Is86zcH?>85%VNV)Ynh&A`1T`d2~P_W&K=-*)-%sOS_znmmtk5>49c)gQ8)wMGUHhz(7KNI zAgk&#s0;o&o-2J@QfvofV_rLO+CM*pyaf0ltqC#3rWhr1HrcA6Ub7uVgtP6#qpGRf z=G+nOG;$QrA2kO2Q~;x3+*UAlTqrp7G?jdl?raOO#0*z{DG8Gu_~{IkG48g5VqJ8Q z*%C=ya}RF2BfV_H6#b54JCcjtGMWJPU4Mb$PA%C)ZA!{za@gdrU+C5llbQS0EpJPx zlBhy&a}sI~1Bo964)7`LF{G5H-zK;MX&=h2Y)@xJ&Vr=c)VlKH&SXanW4di`J+$dD zR1RVTf*S$oc65@VFS zmXmg!OVC%&Gm1o?Kw|OS<77Q-<5K*O(!fGpB`QawL*DQ3TP**=JE9CeywRKs8M^N) he3C{2IIH}3U-tj2Ptt#fLi&HT^nU|np5U*k{{krNlj#5e literal 0 HcmV?d00001 diff --git a/lambda_notify.py b/lambda_notify.py new file mode 100644 index 0000000..8ce5637 --- /dev/null +++ b/lambda_notify.py @@ -0,0 +1,109 @@ +import json +import shlex +import urllib2 +import slack +import boto3 +from itertools import groupby + +# Mapping CloudFormation status codes to colors for Slack message attachments +# Status codes from http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-describing-stacks.html +STATUS_COLORS = { + 'CREATE_COMPLETE': 'good', + 'CREATE_IN_PROGRESS': 'good', + 'CREATE_FAILED': 'danger', + 'DELETE_COMPLETE': 'good', + 'DELETE_FAILED': 'danger', + 'DELETE_IN_PROGRESS': 'good', + 'ROLLBACK_COMPLETE': 'warning', + 'ROLLBACK_FAILED': 'danger', + 'ROLLBACK_IN_PROGRESS': 'warning', + 'UPDATE_COMPLETE': 'good', + 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS': 'good', + 'UPDATE_IN_PROGRESS': 'good', + 'UPDATE_ROLLBACK_COMPLETE': 'warning', + 'UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS': 'warning', + 'UPDATE_ROLLBACK_FAILED': 'danger', + 'UPDATE_ROLLBACK_IN_PROGRESS': 'warning' +} + +# List of CloudFormation status that will trigger a call to `get_stack_summary_attachment` +DESCRIBE_STACK_STATUS = [ + 'CREATE_COMPLETE', + 'DELETE_IN_PROGRESS' +] + +# List of properties from ths SNS message that will be included in a Slack message +SNS_PROPERTIES_FOR_SLACK = [ + 'StackId', + 'ResourceStatus', + 'ResourceType', + 'Timestamp', + 'StackName', +] + + +def lambda_handler(event, context): + message = event['Records'][0]['Sns'] + sns_message = message['Message'] + cf_message = dict(token.split('=', 1) for token in shlex.split(sns_message)) + + # ignore messages that do not pertain to the Stack as a whole + if not cf_message['ResourceType'] == 'AWS::CloudFormation::Stack': + return + + message = get_stack_update_message(cf_message) + data = json.dumps(message) + req = urllib2.Request(slack.WEBHOOK, data, {'Content-Type': 'application/json'}) + urllib2.urlopen(req) + + +def get_stack_update_message(cf_message): + attachments = [ + get_stack_update_attachment(cf_message) + ] + + if cf_message['ResourceStatus'] in DESCRIBE_STACK_STATUS: + attachments.append(get_stack_summary_attachment(cf_message['StackName'])) + + message = { + 'icon_emoji': ':cloud:', + 'username': 'cf-bot', + 'text': 'Cloud Formation stack change in {}'.format(cf_message['StackName']), + 'attachments': attachments + } + + if slack.CHANNEL: + message['channel'] = slack.CHANNEL + + return message + + +def get_stack_update_attachment(cf_message): + title = 'Stack {stack} is now status {status}'.format( + stack=cf_message['StackName'], + status=cf_message['ResourceStatus']) + + return { + 'fallback': title, + 'title': title, + 'fields': [{'title': k, 'value': v, 'short': True} + for k, v in cf_message.iteritems() if k in SNS_PROPERTIES_FOR_SLACK], + 'color': STATUS_COLORS.get(cf_message['ResourceStatus'], '#000000'), + } + + +def get_stack_summary_attachment(stack_name): + client = boto3.client('cloudformation') + resources = client.describe_stack_resources(StackName=stack_name) + sorted_resources = sorted(resources['StackResources'], key=lambda res: res['ResourceType']) + grouped_resources = groupby(sorted_resources, lambda res: res['ResourceType']) + resource_count = {key: len(list(group)) for key, group in grouped_resources} + + title = 'Breakdown of all {} resources'.format(len(resources['StackResources'])) + + return { + 'fallback': title, + 'title': title, + 'fields': [{'title': 'Type {}'.format(k), 'value': 'Total {}'.format(v), 'short': True} + for k, v in resource_count.iteritems()] + }