diff --git a/config/crd/v1/bases/velero.io_backups.yaml b/config/crd/v1/bases/velero.io_backups.yaml index 9aa001f4f..81d51232f 100644 --- a/config/crd/v1/bases/velero.io_backups.yaml +++ b/config/crd/v1/bases/velero.io_backups.yaml @@ -430,8 +430,8 @@ spec: "objectname". nullable: true type: object - resourcePolices: - description: ResourcePolicies specifies the referenced resource policies + resourcePolicy: + description: ResourcePolicy specifies the referenced resource policies that backup should follow properties: apiGroup: diff --git a/config/crd/v1/bases/velero.io_schedules.yaml b/config/crd/v1/bases/velero.io_schedules.yaml index 78a4f2f3d..2d72cb5f2 100644 --- a/config/crd/v1/bases/velero.io_schedules.yaml +++ b/config/crd/v1/bases/velero.io_schedules.yaml @@ -466,8 +466,8 @@ spec: simply use "objectname". nullable: true type: object - resourcePolices: - description: ResourcePolicies specifies the referenced resource + resourcePolicy: + description: ResourcePolicy specifies the referenced resource policies that backup should follow properties: apiGroup: diff --git a/config/crd/v1/crds/crds.go b/config/crd/v1/crds/crds.go index 0011be428..c9aa6361a 100644 --- a/config/crd/v1/crds/crds.go +++ b/config/crd/v1/crds/crds.go @@ -30,14 +30,14 @@ import ( var rawCRDs = [][]byte{ []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4WAo\xdc6\x13\xbd\xebW\f\xf2\x1dr\xf9\xa4M\xd0C\v\xddR\xb7\x05\x82&\x86a\a\xbe\x14=P\xe4\xec.c\x8ad\xc9\xe1\xa6ۢ\xff\xbd\x18R\xf2j%\xd9\x1b\a\xa8n\"\x87of\xde\xcc\x1bQU]ו\xf0\xfa\x1eC\xd4ζ \xbc\xc6?\t-\xbf\xc5\xe6\xe1\x87\xd8h\xb79\xbc\xad\x1e\xb4U-\\\xa5H\xae\xbf\xc5\xe8R\x90\xf8\x13n\xb5դ\x9d\xadz$\xa1\x04\x89\xb6\x02\x10\xd6:\x12\xbc\x1c\xf9\x15@:K\xc1\x19\x83\xa1ޡm\x1eR\x87]\xd2Fa\xc8\xe0\xa3\xebÛ\xe6\xfb\xe6M\x05 \x03\xe6\xe3\x9ft\x8f\x91D\xef[\xb0ɘ\n\xc0\x8a\x1e[\xe8\x84|H>\xa0wQ\x93\v\x1acs@\x83\xc15\xdaUѣd\xb7\xbb\xe0\x92o\xe1\xb4QN\x0f!\x95t~\xcc@\xb7#\xd01o\x19\x1d\xe9\xd7\xd5\xed\x0f:R6\xf1&\x05a\xd6\x02\xc9\xdbQ\xdb]2\",\f\xd8A\x94\xcec\v\xd7\x1c\x8b\x17\x12U\x050P\x90c\xabA(\x95I\x15\xe6&hK\x18\xae\x9cI\xfdHf\r\x9f\xa3\xb37\x82\xf6-4#\xed͂\xb2l;\x12\xf6n\x87\xc3;\x1dٹ\x12\x84K0f\xae9\xc5\xfa\xe9\xe8\xf1\f\xe5D\x04L\xf6\nb\xa4\xa0\xed\xae:\x19\x1f\xde\x16*\xe4\x1e{\xd1\x0e\xb6Σ}w\xf3\xfe\xfe\xbb\xbb\xb3e\x00\x1f\x9c\xc7@z,Oy&}9Y\x05P\x18eОr\u05fcf\xc0b\x05\x8a\x1b\x12#\xd0\x1eGNQ\r1\x80\xdb\x02\xedu\x84\x80>`D[Z\xf4\f\x18\xd8HXp\xddg\x94\xd4\xc0\x1d\x06\x86\x81\xb8w\xc9(\xee\xe3\x03\x06\x82\x80\xd2\xed\xac\xfe\xeb\x11;\x02\xb9\xec\xd4\b¡GNO\xae\xa1\x15\x06\x0e\xc2$\xfc?\b\xab\xa0\x17G\b\xc8^ \xd9\t^6\x89\r|t\x01AۭkaO\xe4c\xbb\xd9\xec4\x8dz\x94\xae\xef\x93\xd5t\xdcdi\xe9.\x91\vq\xa3\xf0\x80f\x13\xf5\xae\x16A\xee5\xa1\xa4\x14p#\xbc\xaes\xe86k\xb2\xe9\xd5\xff\u00a0\xe0\xf8\xfa,\xd6E-˓\xc5\xf2L\x05X-\xa0#\x88\xe1h\xc9\xe2D4/1;\xb7?\xdf}\x82\xd1u.Ɯ\xfd\xcc\xfb\xe9`<\x95\x80\t\xd3v\x8b\xa1\x14q\x1b\\\x9f1\xd1*ﴥ\xfc\"\x8dF;\xa7?\xa6\xae\xd7\xc4u\xff#a$\xaeU\x03WyHA\x87\x90<\xabA5\xf0\xde\u0095\xe8\xd1\\\x89\x88\xffy\x01\x98\xe9X3\xb1_W\x82\xe9|\x9d\x1b\x17\xd6&\x1b\xe3\b|\xa2^\xf3\xb1v\xe7Qr\xf9\x98A>\xaa\xb7Zfm\xc0\xd6\x05\x10\v\xfb\xe6\fz]\xba\xfc\x94\xe1wG.\x88\x1d~p\x05sn\xb4\x1a\xdb\xec\xcc\x18\x1cO\x96\"c\\7\\`\x03\xd0^\xd0D\xbf$\xb4}\x1c\x03\xab\xf90\x92-S\bhi\x80\xc97\x88o\x1e\x99FD\x9a\x8c\v\xbe\xcd]\xe8\x80\x0f\xcb\x13c`\f\x06\xc4\v\xd3\xf9\xf2E̿\xba\xb9hk\x93e\xebB/\xa8\\\x17k\x06ZX\xf0\xb5\\t\x06[\xa0\x90\x96\xdb\xcf\xcdQ\x8cQ\xec.e\xf7\xb1X\x95\xcb\xc5p\x04D\xe7\x12=A=\xed\x97Q\xc0\x85r\\\x88\xd4\xefE\xbc\x14\xe7\r۬5\xc4\xec{\xf5\\\bO\xcd\xcck\xfc\xb2\xb2z\x8bB-u\\õ\xa3\xf5\xad'3\\U\xc5b1\xf2=LM\xea\x1c\x8b\x90\xa7+\xa9{\xbcW\xb6\xf0\xf7?\xd5IXBJ\xf4\x84\xeaz\xfe\a6\xcc\xf7\xf1\x87*\xbfJg\xcb\x0fPl\xe1\xb7߫\xe2\n\xd5\xfd\xf8\x93ċ\xff\x06\x00\x00\xff\xff\xc8p\x98۸\x0e\x00\x00"), - []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec=Ms\xdc:rw\xfd\x8a.\xe5\xe0ݔf\xb4\xae\x1c\x92\xd2\xcd+\xdb\xc9\xd4{\xf1SYZ\xef!\xc9\x01C\xf6\xcc\xe0\t\x04\xb8\x008\xf2l*\xff=\x85/~\x82$8\x1e\xbd\xf8\xa5̋-\x0e\xd0ht7\xfa\v\r\xf0j\xb5Z]\x91\x92~A\xa9\xa8\xe0w@J\x8a_5r\xf3\x97Z?\xff\x8bZSq{|{\xf5Ly~\a\xf7\x95Ң\xf8\x8cJT2\xc3\xf7\xb8\xa3\x9cj*\xf8U\x81\x9a\xe4D\x93\xbb+\x00¹\xd0ļV\xe6O\x80Lp-\x05c(W{\xe4\xeb\xe7j\x8bۊ\xb2\x1c\xa5\x05\x1e\x86>\xfei\xfd\xcf\xeb?]\x01d\x12m\xf7'Z\xa0Ҥ(\xef\x80W\x8c]\x01pR\xe0\x1dlI\xf6\\\x95j}D\x86R\xac\xa9\xb8R%ff\xac\xbd\x14Uy\a\xcd\x0f\xae\x8b\xc7\xc3\xcd\xe1϶\xb7}\xc1\xa8\xd2?\xb5^\xfeL\x95\xb6?\x94\xac\x92\x84\xd5#\xd9w\x8a\xf2}ň\fo\xaf\x00T&J\xbc\x83Of\x88\x92d\x98_\x01\xf8\xe9\xd8!W\x1e\xe1\xe3[\a!;`A\x1c.\x00\xa2D\xfe\xeea\xf3\xe5\x9f\x1e;\xaf\x01rT\x99\xa4\xa5\xb6Dq\x88\x01U@\xe0\x8b\x9d\x16HO~\xd0\a\xa2Ab)Q!\xd7\n\xf4\x01!#\xa5\xae$\x82\xd8\xc1O\xd5\x16%G\x8d\xaa\x06\r\x90\xb1Ji\x94\xa04\xd1\bD\x03\x81RP\xae\x81rд@\xf8û\x87\r\x88\xed\xaf\x98i\x05\x84\xe7@\x94\x12\x19%\x1as8\nV\x15\xe8\xfa\xfeq]C-\xa5(Qj\x1a\xe8잖T\xb5\xde\xf6\xa6\xf7\xc6P\xc0\xb5\x82܈\x13\xbaix*b\xee\x89f\xe6\xa3\x0fT5ӵ\x12\xd2\x01\f\xa6\x11\xe1\x1e\xf95<\xa24`@\x1dD\xc5r#\x85G\x94\x86`\x99\xd8s\xfa\xf7\x1a\xb6\x02-젌h\xf4\x02\xd0<\x94k\x94\x9c08\x12V\xe1\x8d%IAN ь\x02\x15o\xc1\xb3M\xd4\x1a\xfe]H\x04\xcaw\xe2\x0e\x0eZ\x97\xea\xee\xf6vOuXM\x99(\x8a\x8aS}\xba\xb5\v\x83n+-\xa4\xba\xcd\xf1\x88\xecV\xd1\xfd\x8a\xc8\xec@5f\x86\x91\xb7\xa4\xa4+\x8b:\xb7+j]\xe4\xff\x10\x04@\xbd\xe9\xe0\xaaOF\x18\x95\x96\x94\xef[?X\xa9\x9f\xe0\x80Y\x00N\xbe\\W7\x8b\x86\xd0敡\xce\xe7\x0f\x8fOm٣\xaaO}K\xf7\x96@6,0\x04\xa3|\x87\xd21q'Eaa\"ϝ\xf4Y\xd1e\x14y\x9f\xfc\xaa\xda\x16T\x1b\xbe\xff\xadBe\x84\\\xac\xe1ު\x18\xd8\"Ten$s\r\x1b\x0e\xf7\xa4@vO\x14\xbe:\x03\f\xa5\xd5\xca\x106\x8d\x05m\xed\xd8o\xec\xa8\xd6\xfa!\xe8\xb2\x11~9\x85\xf0Xb\xd6Y0\xa6\x17\xdd\xd1\xcc.\v\xd8\t\xd9\xe8\v\xa7\xae\xd6\x1d\x90\xf1%k\x9eL\xd1GNJu\x10\xda\xe8_Q\xe9~\x8b\x1eB\xf7\x8f\x9b^\x87\x80\x8cGͪ\x95Jan\xd6\xd9\v\xa1ڠ7\x80\t\x06\x10|\xb1\x1a&\xc0\xb3\x9a\xa6R\xa0+\xc9\xed*\xfd\x8c$?=\x89\xbf(\x84\xbc\xb2\xc2\x1al\xc5\rlq'$F\xe0J4\xfdMc\x94\xd2\x10FY\x94D\xa5\xd7\xf0t@CFR1\xed\xe5\x9e*x\xfb'((\xaf4\xae\a\xd0F\x18\xec\x88b\xc1\xb8\x19\xa8'\xf1Q9V͐\xef\xfdH\xb7\x16\x11_\x0e\xa8\x0f(\xa1\x14A\x05Gf\xb9\xa3\fA\x9d\x94\xc6\xc2s<(\xbe\xad\xa7\xbe\x15\n\xc6<\b\x05\xdbS\xc0y8Ocoɖ\xe1\x1dhY\r\x87sd\xd8\n\xc1\x90\xf4\x95p\x9f\x0e\x9fQi\x9a\xcdP\xe1\xbaO\x06\xd7+B\x04\xe9\u007f\xb0s\x8b\xd0a\xdbȚ&\xcf\b$P\xc3\x18\a\xc6ZD\xecP\x00\xfe\x93\xc3{\xa3\xb92\xa3O\x86\u0602\xd7\\\x14\x99Ֆ\\\x00\x13|\x8fҍf\xac\xc2\ve\xcc\f/\xb1\x10G\xcc\xc1(\f\x89\xcch>\xd8UF\x97\f\xe9\f`dyT\x06(W\x1aI\xbe\xbe\xbe$\x83\xf0kƪ\x1c\xf3{\xe7\n<\x1a'&\xb8t\x03u\xd0\xe3Ӈ\xa9\xbeފ0\x9aY\xff\xa3v5L\xa3\xe8\xba\f\xb6\xe4T\xa2\xf3\xd3\f\xd7\xdd\x00\xd5\xe1\xed\x1cD\x13x4\xe3\xff\x8e\x19\xb3\\\xe27\xfd\x9e\x17\x95\xf8I\xae\xccA4\\\xa9\x87\xff\x1d2\xc5\x1a\x8bGo+\x92\x19\xf2s\xbb\xd7\r\xd0]͐\xfc\x06v\x94i\x94=\xce|\xd3z\xb9\x041R\xec\x9dy\n\xa2\xb3Ç\xaf\xc6\xf3R\xcd\xf6C\"]\xfa\x9d\x9d\xff\x1a\xfc\xf9\xaea\x9e\x81\v6]I%\x16.\r\xfad\xa9ټ\xb1\x1eջO\xefc\xe1O\xf7I\x90\xbc\xc1D\xde\xf5\x90m\x0f\xed\x9d\xf2\xd4ixק\x8eo\\\x82\xfb\x06\b<\xe3\xc9y,\x84\x83a\x0e1\x03\x8dD:C\xe2\xd8L\xbb\x15\xb2gu>\xdb;U\x14\xdc\U000cc9d4f=\x02\x1a\x9c\xa8\xf2[\x02\x86\x92\xe6\x85%\x84ʹ\xa6\x13\x0f\xec6H\xd0E\xf3\x93\x83tE\x12\x9e@\xfb3\xa6Y\xb3\xad\xb5\x85d\x19\xfbF9\x16\x99Up\xa0e\xe2D\x8d\x99\xb3\xb9\x01\xb1\xab7B\xbe\x10F\xf3z '\xf7\x1b>\xee\rw\x9fOBo\xf8\r|\xf8J\x95ߋz/P}\x12ھy\x15r:\xc4\xcf \xa6\xebh\x97\x17wj\xdbС\xbd\xa3\x92 \xdc\xeeٸ\b\xaff\x0fU\xb0\xe1&n\xf1\xf4\xb0\xfbcn\xb8i\xfb\xd0}\x8aJ\xd9-\x13.\xf8ʚ\xcaul$G\xecD\x90Bv82D\xad\x1e\xd4\r\x98\b\xf6\xc9X\x12\xd7\xdf\xed\xf81\x92a\x1e2\xfev\x9f\x8ah\xdc\xd3\f\n\x94\xfb)\xc3\xd1~J\xa3\xdf\xd3PHԺ\xeeY(ai\xa6=<^uG\x13\xd2\xddgeVnB\xab\xc0\xec٦#\xdbS\xe3M\xe7gdM\xac\xf5?f\xa9K\xf2\xdcV\x16\x10\xf6\xb0@\xe3/\xe0\xc5\xd0\xf6;Ĝ\x85,\x88\xdd0\xf8oc\xe6\xac@\xff\x0f\x94\x84ʄ5\xfc\xce\x16\n0\xec\xf4\xf5Y\xac\xf60f\x04\xaa\xc0\xf0\xf7H\xd8p\xe3329at\v2g\xc8\xc5n\xe0\xb1\xdc\xc0\xcbA(gS\xedF\xc5,H\xaa\xe0\xfa\x19O\xd77\x03=p\xbd\xe1\xd7\xce\xc0/V7\xb5\xb7 8;\xc1\xb5\xed{\xfd-NP\xa2$&5\xb3\x05\x19\xa9\xae\xb2\x89%\x83'`:\xd6U\b\xc6͝\xc2:I\x0eK\xa1\"{\xab#\xa8<\b\xa5]f\xb1\xe3\x96.\xc9b\x81\x93!\x9f\xbd\x02\xb2su B\x86\x1d~\xa3\xf6z\tW\xc355\xada]6\xdfg\xc4\x1cP\x13X]7+\xd8\xe9\xd3k\xb7\x99`\a!\x99u.f\xe1\x96Rd\xa8Դ\x88$h\xeb\x99$a\x9d $.\x80q\xdb\xe7\xd3I\xc9\xf0\xa4;\xa4\x86H\v]\xf9\x0f_[\xd9K\xb3\xf8\xcd\xdfs·\x14/\xb0k\xb6(H\xbfN$\t\xc5{\xd73,\x13\x0fȅ\x06r_٥\x9e\xeeAzA\xfa\x1e\xcctA\xf9\xc6\x0e\x00o/n\xd6k%\x89\xe78\xee\xf7\xa1oC\xf4\xfa\x85]\xbd\xa9\x1e\x91\xb0\x99{\x89\x1d\xce\r\xf3\xdc\xc6QL\x04Ʌn\xa7\x13\f\xdcR\xe4o\x14\xec\xa8T\xba\x8dh\xaaPT3\xab\xbfy\x96FN\xfc\x83\x94g\x05N\xbf\xb8\x9e\xadD\xd6A\xbc\x84j\x9b\xd1\u0084\xd8c7\x85\x10\xe8\x0e\xa8\x06䙨\xb8M\xbf\x98\xa5n\x87p,p\n:\x99di\n\xc2<ȫ\"\x8d\x00++u\x94O\xe6i\xda\xcd?\x12\x1a\xdb\x1a\x1e>\v٦NJ\x92bO\x87m\xa1:\xa9]6U\x90\xaf\xb4\xa8\n \x85!}jسs5M\x1d\x8eוM\x16\xae5#Z\x98EU2ԩ+\xd2\xd50\x99e\xa2h\x8e\xb5a\xf6R 8\x10\xd8\x11\xcaFJI\x86\xcf\"\xda.\x895\xbc\xb2\xb8\\\x10\x916\xf8ʒ\"!\x11\x9b\xe8,Nk\xebR\xa6\xbb\x8a\x0f\x12\xd3ܳ\xb9\xa4tp\xcfJI\x8d,\x89K{h^\xc4\b?\xfdp\xd1\x06\xcf\x0f\x17m\xe6\xf9ᢍ>?\\\xb4\xf9燋\xe6\x9f\x1f.Zx~\xb8h?\\\xb4\xa9fS\xdaz\x0e#w\xfej\xe4\xc7Y,\x12\xb6\xa7\xa7P\x9c\x80\xef\xab)|\x11uj\x85\xe5&\xde+R#\uf2e0W\xb6\xfa6&\x01M\xd1EcJ\xea\x92K\xb3@\x82x\xbb\xe3$3E\x98\xdfP\x8b\x1e\x06=\xa7\x16}3\xd5\xf72\xb5\xe8\x1e\xbd\xbe\xcb}\x99J\xf40\xf7\xf8)\x94\bD_\xe0\xe2\xca-\n$!\xc5\xee\xf6\xd3\xf3\x91\x11{\x83\r\xe0\xfe\xc6%\xb4\x83\x12\xaf\xe4\n\xe3A\x85\xd7\xe5\xcb\xdeG\xf8=\xe0O\x04\"UF\x18\xbe?\xf2.\xa6\xea81\xfbd\x8aL*\x1c\x1c5qd\xbb(\xab[\x00\xf7}J\xe4R9L\xadt\x9f\xa2\xd7P\xb1\xb4\b\xf6\xbd\xae`\x8d\xc5/\xa5\xb7\rig\x047\x91.s\xa7\x04#\xf3\xb1A\xbf:\xf1\xec \x05\x17\x95\xf2y\x02\x03\xfd\x9dMW\xf8-L[\xbe\x95\xa8T\xdf\xc2AT\x91J\xeb\t\xda\xcd\xd4ݍW\xdb\xf9\xbde\xd4\xe4\xf8v\xdd\xfdE\v_{\a/T\x1f\"x\xbe\x1c\x90\xdb]q\xbeo\x17҇\x05\xe7\x8f0\xf7\x05\t\x84\x04N٘\x8d\xaa\xcfyw\xcc\xd1/\xa5K\n-\xb6\xf4\xd3\t\x8d\xb4꼳k\xf2\xba5w#N\xdf\xd2M\xe8\xf4\xa3\a\xe9Uw\xd3erKj\xed\xfa\x95t\xa3@\xe7+\xecRrQ3\xd5tg\xd4\xd0%\xd6O\u007f\xf3V{J\x95\xdcY\xb5q\xb3%Ɖ\x15q\xddZ\xb7i\x90\v\xea\xe0\x92\x883_\xf3\xb6\xb8\xd2\xcdW\x96M\xce#\xb9\xbe-R\xb96\tx\xb4\xaam\xaa^m&\xcf=\xaceK\xafR\x9b\x04m+\xd8\xe6k\xd3.W\x81~\x89\xa8z\\\xd5\xcc֗\xcdF\xdd\xd3\xf8\xcdV\x90-\xa9\x1b\x9b\xa5ؙ5bu\r\xd8ȸK+ú\x95_#@S\xea\xc1F\xea\xbdF NV\x81\xa5Vy\x8d\xc0\x9e1\xbb\x93R2\xf1c\xfc\xa2\r\x98\xb5o췒\xa8s'&d\xc7]\x9c\vQ~\xe957\xbc\f^Ӵ\xfb\x19\xf3<\xa9>,w?\x8b\x8aiZ2\xbbAx\xa4y4\r\xa5\x0fx\xaa\xafM\xf8U\u0603\x93ۓ\x85\xf4\xcb\xe7Z<\xd7='\x9a(xAƀĄk0\xf3\xcc\xdd\x15\x93\x89\x15\x1a\x9do\x16\x9c\xbf\x10\xc2_)s\xe3$؞\r\x8d\xed\xa1\xe8\x03\x16\x06J\xb8YbA\xfc5\xed :_־\xfb[\x85\xf2\x04∲\xf1\x18fN&\xb9\x85\xa6Lt\x13\x96\xbe\xd7\x1f\ue1a2\x9e\xe3\xdc,8xǝ\t\x8b\x82\xed\xe1h\xe1\x985\xcfj^\x1b\xf5f‑\xa6\xf1T\xaa\xa8{G~\x9f\xf3=S\x8f\xf5\xbcn\xe8\xb0^)\xfcx\x8d\x00\xe4uC\x90\xd9 dVr&\u007f>;\xbd.d\x8err7\"U\xd4&\x85\xac\x17/t\xc7\xec\xe5\xe6\xc3\rj\xa6U\xc75\x8d\xa5\x94\xeb\xf3\xe4\x19\xfcD\xb9\xdf\xdd4Bղ\xe3\x9d-\x92Ʊ\x88g\xe8\x1b\xaf\xcd\xdf0\xe9\xf6U\x14\x96D\xda}\xcf\xed\xc9\x15;\xa85| ١\a\xfd\x10\x8d\x13vB\x16D\xc3u\xbd)u뀛\xbf\xaf\xd7\x00\x1fE\xbd\x8d\u07be\xa3EѢd'\x13\aD`^\xb7A\x9c'\x10Qa\n\xe3?\bF緧>\xb7[\xd3\xc8}\v\xf6>!cGj:\x95\xbei4\xfa!\xbaw\x9f\xe0N0&^\x16Fؤ\xa4\xffj/\xe7\x9dO\xb4\xbc{\xd8ئAX쥾u\xd9N\x8d\xf4\x16\x8d\x11l\xa63\xb6\x887\xbb\x0e\xc4H\xf9[\xfd\xa7\x15\xd8\xda\bӱ+\x8d\\)\x9eQ\x1e\x0f\x1b\x87\xdd\xda\xca\v\xe1'\x10\xb6\x00C\x1f\xa8\xccW%\x91\xfa\xe46\xfcoj\x1cƓ-\xc1\x14N\xa5DF-\xc6\xf0\x96\xd7(m\xc3e\xafv\xc7\xedTv\xf7+\xfb\x14=\a\x8f\xf1\xf3u\xb3'\xeb.\x88ǸW\xb1\xb2\x94\x8a\xbc\x8eV\nM,J\xe5\xef(\xf5\x976\xce,\xca\xc7n\xebH\xcdN\xb8\xaf2\xc0U\xf1l\x84\x91\xb1\x87/6d\xa8ױ7\xe2>(\b)\x99\xfe\x15j\u007f\xbe|\xf5\x8e\xd2B\x92=\xfe,ܵ\xb3s4\xe8\xb6\xee\xdc9\xecMy\xa8\xa6\v\"\x11sq\xfd\x05\xb8=`M\x91\xec\xe0\xf2S\x83elUMH\x90\xd6lf2OO?\xbb\thZ\xe0\xfa}\xe5v\x9d͒Wh\xa8\x19&\xe6:m\xcd\u007f\x0f\x11\xa5\t\xf6\x16\xd1\x16\u007fZxK\xb4\x85\xb8\xb6 k\x11\xf6\xc7\xce%\xba\x81Ds\"\xfa%ޫ\x957i1ə\u0a04\x8e\xc1i\xdd#n3\x8a\xf6 \xede\xef\xf5\x1bs\xaa\xc6nZ\xb6\xb7\v\xcfߵ\xec.!\xf67\xab\xfbr\xeeJ\xdaK\xf9\xfc\x05\xc5\xf6\x12\xbb\xb3\xae[\xde\xd6\x15\fu}\x84z\xa7\xb5\t\x00c\xea+\x82\xdeH\xdfZ\xcb\vM\x18\xf0\xaa\xd8Z\xdf-\xa6R\xea.\xb6\xb6b\xb2\xa8\xc2Y\xe1\t\xc69RS\xaeq?H&\xc7\xe6z\xef\xaboϙk\xdd7}\xae\xaa\xca2TjW1v\xaa+\u007f\x97L<\x02\xf3R\xa4\xf8H(;\x8b\x0e\xae\xe3\b\x11\xdc\xdcF\xf5h\x12\x9b}\xc9!\xf2<,ށ)0\x8f\xad\x87_F\aς\xce\xc7\x1e\xa6\tp?\xeca\xaf\xf4\x97y\xab\x8e\xa8\xbe\xf4\xf9\x85\xa8\x86\xcd1Ǫ\x01\xe7zZ?\xcc@\xc3\x1c\xf0\x88\x1c\x04\xb7\xf5\xdc\xf6\xb6G\xf7ى~\x9f\b\xd46\x14_0^\x95L\x90<\x18\xb8\x10Q\xf9O\x15\x16\xd8\xf2#1,\x88\xb1H-~\x14l\x05\x9fp\x18X\xb8\xd3]\x98ۭ\xa1طrL\x93\r\u007f\x90b/Q\rW\xd5\n\xfeJ\xa8\xa6|\xffQ\xc8\aV\xed)o\xfc\x8dE\x8d\x1f\x88Ԕ0vr\xf8\xc4\x10\xa5\x9c0\xfa\xf7\x18w\xda?\xce\x03\xaa\xd5m\xe4\xb7\x044\xc6~x\x8f\xc6Ԏ\x86\x1bqA\xf0t\x9d\x93\x05߬IeS\xeedמ$ۊJw\x94_\xa3<#\x82\x1c\xc6\\\xc3'\xa11\xec\x90\xd2.Lc.P\xe9\x15\xeevBj\x979_\xad\x80\xee|\xf8\x12K\x95\x12\xcal\x85\x87\xfb\xd8\x0eP\xdd\x14\xb95\xeb\xcdf&\xa4U\x1b\xf6\x0eւ\x9c\\\x12\x8dd\x99\x89\x8e\xf1Vi\xc2\"\x1a\xf9\x9bj\x8am\x9ch\xd6\v\xe6\u007fI\xc9-n\xda\xed\xeb\x04Tm\x8f-8G9{\xea\xd3Y\xa3\xa8m\x06{\x16\x109\xbcH\xaa\xb5\xb1\x00\xed\x12\x18\xd0F\xe73\x06\xcah\xc1\x91\x8b\xbc\xa7l\x91\xfd\xddx\v\x9b\xf1-\xb9nB\xa2n<\xe6l\xf8\xc9\tÖ\xad%\xc1ȴܑ\x17\xaaB_\xc3\xca\xec@\xf8\xde\b\x95\x14\xd5\xfe\x10\xe4rĖ\x8f\xc0\xcd+\x83\x14\x94VC\xa8P~\xa0+\xc9[[\x1a\xf5i\xa6\x06]\x92=\x8fb\xea\xb7X\xc3\a\xdfn\xfd\xd5ܫ\x9d\x14\xc5\xca\xf3\xc2V\r\xdc\xf8m\x06I\x85\t\xd8\xf5!Jrp_\xd2\xf1w\xe0Z1(K\xe4@\x94\xc7'\xe1ʃi\xb6N\xa5\x145\x91:5\x0ez\xec4\x9e\t\x81,\xe48\xbe\x8f~\x1b\xc5]\xfdp\xdf\xff\xf4\xde\r(\xca÷\xe6\xdc&\x8d\x13\x05e\"#\x896\xb9\x16-\b\x19\xc44\x9d\b\xa6\x8b\xfeo\x1b\xbc\x1ck\x9b\xf8!\xc5\v\xfe\xd2k\xde;\xeec?\xa9T7\xf1\x9ek\x84\x1e\u007f\xa0;W\xa3\x92\x19\xac\xff\xf8\u007f~\x8c\xe7\x98\xe4e\xbd\x99t\xb0\xac\xefT{J3\x1fPz`h<\x1f\x85\xd8\xf5\xdd\xde,rҏ煝\x97\x8c9\xc3g\x10/\x13\x89\x1dϋ6_-Լ\xec\xec^\x88\xfd\xf4\xda\xdc\x1a\xfb\xabo\x16\x895=\x84H\xb4\x19\x99F\x1d\u007f\xceF\x9b\xad`3\xe08\xf2=\x9a^\x00z\xa1p3j\a\x06/\xad\x02\xcd[kۏ\xe4\xdf4\x19l\x92eh\xc4\xf5S\xffs\xa7\xd7\xee\xdbaዦ\xf6\xcfLpgn\xd5\x1d\xfc\xc7\u007f]\x81\xdf\"\xf9\x12>]j^\xfeo\x00\x00\x00\xff\xff\x16\xad\x10\xed\x1av\x00\x00"), + []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec=Ms\xdc:rw\xfd\x8a.\xe5\xe0ݔf\xb4\xae\x1c\x92\xd2\xcd+\xdb\xc9\xd4{\xf1SYZ\xef!\xc9\x01C\xf6\xcc\xe0\t\x04\xb8\x008\xf2l*\xff=\x85/~\x82$8\x1e\xbd\xf8\xa5̋-\x0e\xd0ht7\xfa\v\r\xf0j\xb5Z]\x91\x92~A\xa9\xa8\xe0w@J\x8a_5r\xf3\x97Z?\xff\x8bZSq{|{\xf5Ly~\a\xf7\x95Ң\xf8\x8cJT2\xc3\xf7\xb8\xa3\x9cj*\xf8U\x81\x9a\xe4D\x93\xbb+\x00¹\xd0ļV\xe6O\x80Lp-\x05c(W{\xe4\xeb\xe7j\x8bۊ\xb2\x1c\xa5\x05\x1e\x86>\xfei\xfd\xcf\xeb?]\x01d\x12m\xf7'Z\xa0Ҥ(\xef\x80W\x8c]\x01pR\xe0\x1dlI\xf6\\\x95j}D\x86R\xac\xa9\xb8R%ff\xac\xbd\x14Uy\a\xcd\x0f\xae\x8b\xc7\xc3\xcd\xe1϶\xb7}\xc1\xa8\xd2?\xb5^\xfeL\x95\xb6?\x94\xac\x92\x84\xd5#\xd9w\x8a\xf2}ň\fo\xaf\x00T&J\xbc\x83Of\x88\x92d\x98_\x01\xf8\xe9\xd8!W\x1e\xe1\xe3[\a!;`A\x1c.\x00\xa2D\xfe\xeea\xf3\xe5\x9f\x1e;\xaf\x01rT\x99\xa4\xa5\xb6Dq\x88\x01U@\xe0\x8b\x9d\x16HO~\xd0\a\xa2Ab)Q!\xd7\n\xf4\x01!#\xa5\xae$\x82\xd8\xc1O\xd5\x16%G\x8d\xaa\x06\r\x90\xb1Ji\x94\xa04\xd1\bD\x03\x81RP\xae\x81rд@\xf8û\x87\r\x88\xed\xaf\x98i\x05\x84\xe7@\x94\x12\x19%\x1as8\nV\x15\xe8\xfa\xfeq]C-\xa5(Qj\x1a\xe8잖T\xb5\xde\xf6\xa6\xf7\xc6P\xc0\xb5\x82܈\x13\xbaix*b\xee\x89f\xe6\xa3\x0fT5ӵ\x12\xd2\x01\f\xa6\x11\xe1\x1e\xf95<\xa24`@\x1dD\xc5r#\x85G\x94\x86`\x99\xd8s\xfa\xf7\x1a\xb6\x02-젌h\xf4\x02\xd0<\x94k\x94\x9c08\x12V\xe1\x8d%IAN ь\x02\x15o\xc1\xb3M\xd4\x1a\xfe]H\x04\xcaw\xe2\x0e\x0eZ\x97\xea\xee\xf6vOuXM\x99(\x8a\x8aS}\xba\xb5\v\x83n+-\xa4\xba\xcd\xf1\x88\xecV\xd1\xfd\x8a\xc8\xec@5f\x86\x91\xb7\xa4\xa4+\x8b:\xb7+j]\xe4\xff\x10\x04@\xbd\xe9\xe0\xaaOF\x18\x95\x96\x94\xef[?X\xa9\x9f\xe0\x80Y\x00N\xbe\\W7\x8b\x86\xd0敡\xce\xe7\x0f\x8fOm٣\xaaO}K\xf7\x96@6,0\x04\xa3|\x87\xd21q'Eaa\"ϝ\xf4Y\xd1e\x14y\x9f\xfc\xaa\xda\x16T\x1b\xbe\xff\xadBe\x84\\\xac\xe1ު\x18\xd8\"Ten$s\r\x1b\x0e\xf7\xa4@vO\x14\xbe:\x03\f\xa5\xd5\xca\x106\x8d\x05m\xed\xd8o\xec\xa8\xd6\xfa!\xe8\xb2\x11~9\x85\xf0Xb\xd6Y0\xa6\x17\xdd\xd1\xcc.\v\xd8\t\xd9\xe8\v\xa7\xae\xd6\x1d\x90\xf1%k\x9eL\xd1GNJu\x10\xda\xe8_Q\xe9~\x8b\x1eB\xf7\x8f\x9b^\x87\x80\x8cGͪ\x95Jan\xd6\xd9\v\xa1ڠ7\x80\t\x06\x10|\xb1\x1a&\xc0\xb3\x9a\xa6R\xa0+\xc9\xed*\xfd\x8c$?=\x89\xbf(\x84\xbc\xb2\xc2\x1al\xc5\rlq'$F\xe0J4\xfdMc\x94\xd2\x10FY\x94D\xa5\xd7\xf0t@CFR1\xed\xe5\x9e*x\xfb'((\xaf4\xae\a\xd0F\x18\xec\x88b\xc1\xb8\x19\xa8'\xf1Q9V͐\xef\xfdH\xb7\x16\x11_\x0e\xa8\x0f(\xa1\x14A\x05Gf\xb9\xa3\fA\x9d\x94\xc6\xc2s<(\xbe\xad\xa7\xbe\x15\n\xc6<\b\x05\xdbS\xc0y8Ocoɖ\xe1\x1dhY\r\x87sd\xd8\n\xc1\x90\xf4\x95p\x9f\x0e\x9fQi\x9a\xcdP\xe1\xbaO\x06\xd7+B\x04\xe9\u007f\xb0s\x8b\xd0a\xdbȚ&\xcf\b$P\xc3\x18\a\xc6ZD\xecP\x00\xfe\x93\xc3{\xa3\xb92\xa3O\x86\u0602\xd7\\\x14\x99Ֆ\\\x00\x13|\x8fҍf\xac\xc2\ve\xcc\f/\xb1\x10G\xcc\xc1(\f\x89\xcch>\xd8UF\x97\f\xe9\f`dyT\x06(W\x1aI\xbe\xbe\xbe$\x83\xf0kƪ\x1c\xf3{\xe7\n<\x1a'&\xb8t\x03u\xd0\xe3Ӈ\xa9\xbeފ0\x9aY\xff\xa3v5L\xa3\xe8\xba\f\xb6\xe4T\xa2\xf3\xd3\f\xd7\xdd\x00\xd5\xe1\xed\x1cD\x13x4\xe3\xff\x8e\x19\xb3\\\xe27\xfd\x9e\x17\x95\xf8I\xae\xccA4\\\xa9\x87\xff\x1d2\xc5\x1a\x8bGo+\x92\x19\xf2s\xbb\xd7\r\xd0]͐\xfc\x06v\x94i\x94=\xce|\xd3z\xb9\x041R\xec\x9dy\n\xa2\xb3Ç\xaf\xc6\xf3R\xcd\xf6C\"]\xfa\x9d\x9d\xff\x1a\xfc\xf9\xaea\x9e\x81\v6]I%\x16.\r\xfad\xa9ټ\xb1\x1eջO\xefc\xe1O\xf7I\x90\xbc\xc1D\xde\xf5\x90m\x0f\xed\x9d\xf2\xd4ixק\x8eo\\\x82\xfb\x06\b<\xe3\xc9y,\x84\x83a\x0e1\x03\x8dD:C\xe2\xd8L\xbb\x15\xb2gu>\xdb;U\x14\xdc\U000cc9d4f=\x02\x1a\x9c\xa8\xf2[\x02\x86\x92\xe6\x85%\x84ʹ\xa6\x13\x0f\xec6H\xd0E\xf3\x93\x83tE\x12\x9e@\xfb3\xa6Y\xb3\xad\xb5\x85d\x19\xfbF9\x16\x99Up\xa0e\xe2D\x8d\x99\xb3\xb9\x01\xb1\xab7B\xbe\x10F\xf3z '\xf7\x1b>\xee\rw\x9fOBo\xf8\r|\xf8J\x95ߋz/P}\x12ھy\x15r:\xc4\xcf \xa6\xebh\x97\x17wj\xdbС\xbd\xa3\x92 \xdc\xeeٸ\b\xaff\x0fU\xb0\xe1&n\xf1\xf4\xb0\xfbcn\xb8i\xfb\xd0}\x8aJ\xd9-\x13.\xf8ʚ\xcaul$G\xecD\x90Bv82D\xad\x1e\xd4\r\x98\b\xf6\xc9X\x12\xd7\xdf\xed\xf81\x92a\x1e2\xfev\x9f\x8ah\xdc\xd3\f\n\x94\xfb)\xc3\xd1~J\xa3\xdf\xd3PHԺ\xeeY(ai\xa6=<^uG\x13\xd2\xddgeVnB\xab\xc0\xec٦#\xdbS\xe3M\xe7gdM\xac\xf5?f\xa9K\xf2\xdcV\x16\x10\xf6\xb0@\xe3/\xe0\xc5\xd0\xf6;Ĝ\x85,\x88\xdd0\xf8oc\xe6\xac@\xff\x0f\x94\x84ʄ5\xfc\xce\x16\n0\xec\xf4\xf5Y\xac\xf60f\x04\xaa\xc0\xf0\xf7H\xd8p\xe3329at\v2g\xc8\xc5n\xe0\xb1\xdc\xc0\xcbA(gS\xedF\xc5,H\xaa\xe0\xfa\x19O\xd77\x03=p\xbd\xe1\xd7\xce\xc0/V7\xb5\xb7 8;\xc1\xb5\xed{\xfd-NP\xa2$&5\xb3\x05\x19\xa9\xae\xb2\x89%\x83'`:\xd6U\b\xc6͝\xc2:I\x0eK\xa1\"{\xab#\xa8<\b\xa5]f\xb1\xe3\x96.\xc9b\x81\x93!\x9f\xbd\x02\xb2su B\x86\x1d~\xa3\xf6z\tW\xc355\xada]6\xdfg\xc4\x1cP\x13X]7+\xd8\xe9\xd3k\xb7\x99`\a!\x99u.f\xe1\x96Rd\xa8Դ\x88$h\xeb\x99$a\x9d $.\x80q\xdb\xe7\xd3I\xc9\xf0\xa4;\xa4\x86H\v]\xf9\x0f_[\xd9K\xb3\xf8\xcd\xdfs·\x14/\xb0k\xb6(H\xbfN$\t\xc5{\xd73,\x13\x0fȅ\x06r_٥\x9e\xeeAzA\xfa\x1e\xcctA\xf9\xc6\x0e\x00o/n\xd6k%\x89\xe78\xee\xf7\xa1oC\xf4\xfa\x85]\xbd\xa9\x1e\x91\xb0\x99{\x89\x1d\xce\r\xf3\xdc\xc6QL\x04Ʌn\xa7\x13\f\xdcR\xe4o\x14\xec\xa8T\xba\x8dh\xaaPT3\xab\xbfy\x96FN\xfc\x83\x94g\x05N\xbf\xb8\x9e\xadD\xd6A\xbc\x84j\x9b\xd1\u0084\xd8c7\x85\x10\xe8\x0e\xa8\x06䙨\xb8M\xbf\x98\xa5n\x87p,p\n:\x99di\n\xc2<ȫ\"\x8d\x00++u\x94O\xe6i\xda\xcd?\x12\x1a\xdb\x1a\x1e>\v٦NJ\x92bO\x87m\xa1:\xa9]6U\x90\xaf\xb4\xa8\n \x85!}jسs5M\x1d\x8eוM\x16\xae5#Z\x98EU2ԩ+\xd2\xd50\x99e\xa2h\x8e\xb5a\xf6R 8\x10\xd8\x11\xcaFJI\x86\xcf\"\xda.\x895\xbc\xb2\xb8\\\x10\x916\xf8ʒ\"!\x11\x9b\xe8,Nk\xebR\xa6\xbb\x8a\x0f\x12\xd3ܳ\xb9\xa4tp\xcfJI\x8d,\x89K{h^\xc4\b?\xfdp\xd1\x06\xcf\x0f\x17m\xe6\xf9ᢍ>?\\\xb4\xf9燋\xe6\x9f\x1f.Zx~\xb8h?\\\xb4\xa9fS\xdaz\x0e#w\xfej\xe4\xc7Y,\x12\xb6\xa7\xa7P\x9c\x80\xef\xab)|\x11uj\x85\xe5&\xde+R#\uf2e0W\xb6\xfa6&\x01M\xd1EcJ\xea\x92K\xb3@\x82x\xbb\xe3$3E\x98\xdfP\x8b\x1e\x06=\xa7\x16}3\xd5\xf72\xb5\xe8\x1e\xbd\xbe\xcb}\x99J\xf40\xf7\xf8)\x94\bD_\xe0\xe2\xca-\n$!\xc5\xee\xf6\xd3\xf3\x91\x11{\x83\r\xe0\xfe\xc6%\xb4\x83\x12\xaf\xe4\n\xe3A\x85\xd7\xe5\xcb\xdeG\xf8=\xe0O\x04\"UF\x18\xbe?\xf2.\xa6\xea81\xfbd\x8aL*\x1c\x1c5qd\xbb(\xab[\x00\xf7}J\xe4R9L\xadt\x9f\xa2\xd7P\xb1\xb4\b\xf6\xbd\xae`\x8d\xc5/\xa5\xb7\rig\x047\x91.s\xa7\x04#\xf3\xb1A\xbf:\xf1\xec \x05\x17\x95\xf2y\x02\x03\xfd\x9dMW\xf8-L[\xbe\x95\xa8T\xdf\xc2AT\x91J\xeb\t\xda\xcd\xd4ݍW\xdb\xf9\xbde\xd4\xe4\xf8v\xdd\xfdE\v_{\a/T\x1f\"x\xbe\x1c\x90\xdb]q\xbeo\x17҇\x05\xe7\x8f0\xf7\x05\t\x84\x04N٘\x8d\xaa\xcfyw\xcc\xd1/\xa5K\n-\xb6\xf4\xd3\t\x8d\xb4꼳k\xf2\xba5w#N\xdf\xd2M\xe8\xf4\xa3\a\xe9Uw\xd3erKj\xed\xfa\x95t\xa3@\xe7+\xecRrQ3\xd5tg\xd4\xd0%\xd6O\u007f\xf3V{J\x95\xdcY\xb5q\xb3%Ɖ\x15q\xddZ\xb7i\x90\v\xea\xe0\x92\x883_\xf3\xb6\xb8\xd2\xcdW\x96M\xce#\xb9\xbe-R\xb96\tx\xb4\xaam\xaa^m&\xcf=\xaceK\xafR\x9b\x04m+\xd8\xe6k\xd3.W\x81~\x89\xa8z\\\xd5\xcc֗\xcdF\xdd\xd3\xf8\xcdV\x90-\xa9\x1b\x9b\xa5ؙ5bu\r\xd8ȸK+ú\x95_#@S\xea\xc1F\xea\xbdF NV\x81\xa5Vy\x8d\xc0\x9e1\xbb\x93R2\xf1c\xfc\xa2\r\x98\xb5o췒\xa8s'&d\xc7]\x9c\vQ~\xe957\xbc\f^Ӵ\xfb\x19\xf3<\xa9>,w?\x8b\x8aiZ2\xbbAx\xa4y4\r\xa5\x0fx\xaa\xafM\xf8U\u0603\x93ۓ\x85\xf4\xcb\xe7Z<\xd7='\x9a(xAƀĄk0\xf3\xcc\xdd\x15\x93\x89\x15\x1a\x9do\x16\x9c\xbf\x10\xc2_)s\xe3$؞\r\x8d\xed\xa1\xe8\x03\x16\x06J\xb8YbA\xfc5\xed :_־\xfb[\x85\xf2\x04∲\xf1\x18fN&\xb9\x85\xa6Lt\x13\x96\xbe\xd7\x1f\ue1a2\x9e\xe3\xdc,8xǝ\t\x8b\x82\xed\xe1h\xe1\x985\xcfj^\x1b\xf5f‑\xa6\xf1T\xaa\xa8{G~\x9f\xf3=S\x8f\xf5\xbcn\xe8\xb0^)\xfcx\x8d\x00\xe4uC\x90\xd9 dVr&\u007f>;\xbd.d\x8err7\"U\xd4&\x85\xac\x17/t\xc7\xec\xe5\xe6\xc3\rj\xa6U\xc75\x8d\xa5\x94\xeb\xf3\xe4\x19\xfcD\xb9\xdf\xdd4Bղ\xe3\x9d-\x92Ʊ\x88g\xe8\x1b\xaf\xcd\xdf0\xe9\xf6U\x14\x96D\xda}\xcf\xed\xc9\x15;\xa85| ١\a\xfd\x10\x8d\x13vB\x16D\xc3u\xbd)u뀛\xbf\xaf\xd7\x00\x1fE\xbd\x8d\u07be\xa3EѢd'\x13\aD`^\xb7A\x9c'\x10Qa\n\xe3?\bF\xb3\x88\xe7\x14\xbd\xb6\xc75\x1e\\\xb6`/\x132F\xa4&Ri\x1a\xc6\x1d'\xebdu/\x13\xdc\t\xc6\xc4\xcb\xc2\xf0\x9a\x94\xf4_\xedͼ\xf3Y\x96w\x0f\x1b\xdb4H\x8a\xbdѷ\xae٩\x91ޢ\xb1\x80\xcdt\xc6V\xf0fׁ\x18\xa9}\xab\xff\xb4\xd2Z[`:v\x9f\x91\xab\xc33\x9a\xe3a\xe3\xb0[[a!\xfc\x04\xc2V_\xe8\x03\x95\xf9\xaa$R\x9f\xdcn\xffM\x8d\xc3x\xa6%\xd8\xc1\xa9|Ȩ\xb9\x18^\xf1\x1a\xa5m\xb8\xe9\xd5n\xb7\x9d\xca\xeefe\x9f\xa2\xe7\xe01~\xb8n\xf6X\xdd\x05\xf1\x18w)V\x96R\x91\xd7\xd12\xa1\x89\x15\xa9\xfc\x05\xa5\xfe\xc6ƙ%\xf9\xd8m\x1d)\xd8\t\x97U\x06\xb8*\x9e\x8a02\xf6\xf0\xc5\xc6\v\xf5:\xf6\x16\xdcG\x04!\x1fӿ?\xedϗ/\xddQZH\xb2ǟ\x85\xbbsv\x8e\x06\xdd֝\v\x87\xbd\x1d\x0f\xa5tA$b\xfe\xad\xbf\xfd\xb6\a\xac\xa9\x90\x1d\xdc|j\xb0\x8c\xad\xaa\t\tҚ\xcdL\xe6\xe9\xe9g7\x01M\v\\\xbf\xafܖ\xb3Y\xf2\n\r5\xc3\xc4\\\xa7\xad\xf9\xef!\xa24\xc1^!\xda\xe2O\vo\x89\xb6\n\xd7Vc-\xc2\xfeعA7\x90hND\xbf\xc4{\xb5\x92&-&9\xfb\x1b\x95\xd018\xadK\xc4m:ў\xa2\xbd\xec\xa5~c\x1e\xd5\xd85\xcb\xf6j\xe1\xf9\x8b\x96\xdd\r\xc4\xfeZu_\xcb]I{#\x9f\xbf\x9d\xd8\xde`w\xd6]\xcbۺ|\xa1.\x8eP\xef\xb46\xd1_L}E\xd0\x1b\xe9[ky\xa1\t\x03^\x15[\xeb\xb8\xc5TJ\xdd\xc5\x16VLVT8+<\xc18Gj\xca5\xee\a\x99\xe4\xd8\\\xef}\xe9\xed9s\xad\xfb\xa6\xcfUUY\x86J\xed*\xc6Nu\xd9\uf489G`^\x8a\x14\x1f\teg\xd1\xc1u\x1c!\x82\x9bۨ\x1eMb\xb3\xaf7D\x9e\x87\xc5;0\x05\xe6\xb1\xc5\xf0\xcb\xe8\xe0Y\xd0\xf9\xd2\xc34\x01\xee\x87=\xec}\xfe2o\x15\x11\xd57>\xbf\x10հ9\xe6X5\xe0\\O\xeb\x87\x19h\x98\x03\x1e\x91\x83\u0d98\xdb^\xf5\xe8\xbe9\xd1\xef\x13\x81چ\xe2\xabū\x92\t\x92\a\x03\x17\xc2)\xff\x9d\x82'k\xbe\xe5\x11\xe5\x1b5\x01\xb3\xbe\xc3;B\x84\xa1d\xba\xf8\xe6\x0er\xa2q\x15\x05\x9ad\xfa\xa3\xba6S\xb4\xab瓕\xd6\xfd\xe3f\xac\xe7\xa8\x04\x87\x061\xfe\rn\x8c\xffF%5\x9cY\xaa\x8a\x1a\xcelNAu\xd4Qdr\x8d\x82\xba\xf84\xedZ\x9d\xbd\xd0\xd76r\x1e\x80=\xf5\x12nPw\xc7^\nT\x8a\xec\xc3M\xbe/\xc6\x01\xdb#G\x1b\x91Gf\xe3s\x96\xcd1\x89\xee=\xb6ns\x85d\xba\"~\x80P\x94\xd6j\xf5&\xa6\x80\x99ػ\xbb\xefi\xf8\xf2G\xf0L\x17\xd2\xe4kIe\x8a'\xfb\xa1nhhc\xf7E-#\x9a/\xb5 \xa3{j\xdc@ä=\x91[\xb2\xc7U&\x18C\xabk\x87x\xbd\xe6b\xf5\x87Q>#Q\xb3S\xfb\xd8n\xeb\x93\xf0\x8e\xdb\xee\x1a8\xe2\xea3\xed\x87;4\x95\xd8|\tg\x80\x90\xb0\x03/\xf2\\\x1d\x15\xa2ߌ\x19b\xdan\x1b\x16\x98\u05eb>\xb5\xe3?!s\xe3c\xa1x\xc4Z\x90_\x85\xbc\x81\x82r\xf3\x0f\xe1\xb9˒\x87\u038b\xf0\xb7\x174\xcf\xe0\xfd`\xda\xd4g\x02[~$\x86\x051\x16\xa9\xc5ρ\xad\xe0\x13\x0e\x03\vw\xb4\vs\xbb/\x14\xfbP\x8ei\xb2\xe1\x0fR\xec%\xaa\xe1\xaaZ\xc1_\tՔ\xef?\n\xf9\xc0\xaa=卿\xb1\xa8\xf1\x03\x91\x9a\x12\xc6N\x0e\x9f\x18\xa2\x94\x13F\xff\x1e\xe3N\xfb\xc7y@\xb5\xba\x8d\xfc\x96\x80\xc6\xd8\x0f\xefј\xda\xd1p#.\b\x9e\xaes\xb2\xe0\x9b5ylʝ\xec\xdacd[Q\xe9\x8e\xf2k\x94gD\x90Øk\xf8$4\x86\xedQڅi\xcc\x05*\xbd\xc2\xddNH\xed\xd2\xe6\xab\x15Н\x0f_byRB\x99-\xefp_\xda\x01\xaa\x9b\n\xb7f\xbd\xd9̄\xb4j\xc3^\xc0Z\x90\x93K\xa2\x91,3\xd11\xde*MXD#\u007fSA\xb1\x8d\x13\xcdz\xc1\xfc/)\xb9\xc5M\xbb}\x9d\x80\xaa\xed\xb1\x05\xe7(g\x8f|:k\x14\xb5\xcd`\x0f\x02\"\x87\x17I\xb56\x16\xa0]\xff\x02\xda\xe8|\xc6@\x19-8r\x8b\xf7\x94-\xb2\xbf\x1boa3\xbe\x1f\xd7MHԍǜ\r?9aز\xb5$\x18\x99\x96;\xefBU\xe8kX\x99\x1d\b\xdf\x1b\xa1\x92\xa2\xda\x1f\x82\\\x8e\xd8\xf2\x11\xb8ye\x90\x82\xd2j\b\x15j\x0ft%yk?\xa3>\xcaԠK\xb2\xe7QL\xfd\xfej\xf8\xdaۭ\xbf\x97{\xb5\x93\xa2Xy^ؒ\x81\x1b\xbf\xc7 \xa90\x01\xbb>DI\x0e\xee3:\xfe\x02\\+\x06e\x89\x1c\x88\xf2\xf8$\xdcw0\xcd֩\x94\xa2&R\xa7\xc6A\x8f\x9d\xc63!\x90\x85\x1c\xc7\xf7\xd1\uf878{\x1f\xee\xfb\xdfݻ\x01Ey\xf8Мۡq\xa2\xa0Ld$\xd1&ע\xd5 \x83\x98\xa6\x13\xc1t\xd1\xffm\x83\x97cm\x13?\xa4x\xc1_z\xcd{g}\xec\xf7\x94\xea&\xdes\x8d\xd0\xe3\x0ft\xe7\nT2\x83\xf5\x1f\xff\xcf\xcf\xf0\x1c\x93\xbc\xac7\x93\x0e\x96\xf5\x9djOi\xe6\xebI\x0f\f\x8d\xe7\xa3\x10\xbb\xbeۛEN\xfa\xf1\xbc\xb0\xf3\x921g\xf8\x06\xe2e\"\xb1\xe3y\xd1櫅\x9a\x97\x9d\xdd\v\xb1\xdf]\x9b[c\u007f\xf5\xcd\"\xb1\xa6\x87\x10\x896#Ө\xe3\xcf\xd9h\xb3\x15l\x06\x1cG>F\xd3\v@/\x14nF\xed\xc0\xe0\xa5U\xa0ykm\xfb\x91\xfc\x9b&\x83M\xb2\f\x8d\xb8~\xea\u007f\xeb\xf4\xda}8,|\xce\xd4\xfe\x99\t\xeḙ\xba\x83\xff\xf8\xaf+\xf0[$_\xc2wK\xcd\xcb\xff\r\x00\x00\xff\xffe\xc2\x16\x05\x17v\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4YKo#\xb9\x11\xbe\xebW\x14f\x0f\xbe\x8cZ\xb3\xc9!\x81.\x81F\x93\x00\x83x\xd6\xc6\xc8q\x0eI\x80\xa5Ȓ\xc45\x9b\xec\xf0!\xad\x12\xe4\xbf\aŇ\xba\xd5ݲ\xe4A\xb2ˋ->\x8aU_\xbdٓ\xe9t:a\x8d|F\xeb\xa4\xd1s`\x8dğ=j\xfa媗\u07fbJ\x9a\xd9\xfe\xfbɋ\xd4b\x0e\xcb༩\xbf\xa23\xc1r\xfc\x84\x1b\xa9\xa5\x97FOj\xf4L0\xcf\xe6\x13\x00\xa6\xb5\xf1\x8c\xa6\x1d\xfd\x04\xe0F{k\x94B;ݢ\xae^\xc2\x1a\xd7A*\x816\x12/W\xef?T\xbf\xab>L\x00\xb8\xc5x\xfcI\xd6\xe8<\xab\x9b9\xe8\xa0\xd4\x04@\xb3\x1a\xe7\xb0f\xfc%4\xce\x1b˶\xa8\fOwU{ThM%\xcd\xc45\xc8\xe9\xea\xad5\xa1\x99C\xbb\x90(d\xb6\x92H\x1f#\xb1U\"v\x9f\x89\xc5u%\x9d\xff\xf3\xe5=\xf7\xd2\xf9\xb8\xafQ\xc12u\x89\xad\xb8\xc5\xed\x8c\xf5?\xb4WOa\xedTZ\x91z\x1b\x14\xb3\x17\x8eO\x00\x1c7\r\xce!\x9en\x18G1\x01ȘEjS`BD-0\xf5h\xa5\xf6h\x97F\x85Z\x9f\xee\x12踕\x8d\x8f('Y \v\x03E\x1ap\x9e\xf9\xe0\xc0\x05\xbe\x03\xe6`\xb1gR\xb1\xb5\xc2\xd9_4+\xffGz\x00?9\xa3\x1f\x99\xdf͡J\xa7\xaaf\xc7\\YM:z\xec\xcc\xf8#\t༕z;\xc6\xd2=s\xfe\x99))NZ\a\xe9\xc0\xef\x10\x14s\x1e\x8c\xb6e,\x1e?\x97ț\x1c(\xfb[ƪ\x82E\xf6\\\xb3\x81\x0f \xa4\xa3\x02\xc0E\xa2C\xb0\xa8<\xa3\xf59x\x1b\xde$>7z#\xb7C\xa1\xbb5\xcd%\x8b\xb9B\xba\x87\xdc2\xdeD\xa1\x89\xac\xa3\xb1f/\x05\xda)\xf9\x87\xdcH\x9e9\t6e\xae\x8dD%\xdcP\xd2\v^\x16E\xb1(ȫ\x99\xba\xa2\xc3\xe5ic,\x8d\x99\xd4ɂ[\x021\xd8\xd8:\xa7T\xedQ\x8bS5rƍ\x89Qˡ\x80\x83\xf4\xbb\x14\x0e\u0558\xdf\xc1\xab\xbeG\xe3\x05\x8fc\xd3=ޟvH;S\x02Ep\xc8-\xfahm\xa8\xc8|Ȕ*\x80/\xc1ŀڏ\x13e\xc4B\xad\x9c~\xc1\xe3\x10h\xb8\xa6\xdc\\\xc2\\g\xf9\x8eJ\xe7°\xc5\rZ\xd4~4\xa8Sgb5z\x8cq]\x18\xee(\xa4sl\xbc\x9b\x99=ڽ\xc4\xc3\xec`\xec\x8b\xd4\xdb)\x01>\xcd\x1e4\x8bm\xc5\xec\xbb\xf8\xe7\x82\xc8O\x0f\x9f\x1e\xe6\xb0\x10\x02\x8cߡ%\xadm\x82*\x86֩o\xde\xc7\x1c\xfb\x1e\x82\x14\u007f\xb8\xfb\x16\\L\x93<\xe7\x06lV\xd1\xfa\x8fT\xa8E\xa6\b\xa2UҊ\xb1@\x99\x92\x94]gm\xa6X3f\x88c\x15fwP`\xa2\f2\x16Q_p\x18L_q\xb3\\\xec^\xf1\xb1RHK-$\xa7B\xec\xdc7J\x83!\xce\xea\xed\x11\xc1\xfa\x15\xf8\xa5\x880.x\x12 \xe7\xc3+\x1c?t\xf7\xb6mY\nO9\xc79\xf4T@9\xd0H9\x90\xd9!r1(p\xa35y\xa37\xc0N\xa1\xee\xce\xf5c\xfc\x1b#\xc4:\xf0\x17\x1c\x01~ \xcaǸ\xb1`\x9c\x8e\x11/\xc1a\f\xbe\xd7\u0600\xeb6\xce\xd9\x12\xed-\xbc,\x17\xb4\xf1\x94&\x19,\x17\xb0\x0eZ(,\x1c\x1dv\xa8\xa9C\x90\x9b\xe3\xf8]4\x9e\xeeW\x05\xd5Xa\xe4\x1a\xbf`;.C\x8a\xe1sX\x1fGj\x82\x1b\x84l,n\xe4\xcf7\b\xf9\x187\x16\xc0\x1b\xe6w \xb5\x93\x02\x81\x8d\xc0\x9f\x8a\xb5\v\x82\x9e\xf2\xffC\x8e\"ߠ\x9e\u05fc=\xb1\xf3\x16\x87/\x18_\xf1\x9fǼ\xed\x84B\xf9\x9d#\xffy-xɏG%ڟ\x1e\f\xfe\x94*,>\x92*Ϙy\x1e\x9ex\xa5R+\xcf\x16c\xceLu\x81\xb1\x16]c\xb4\xa0\xe6\xe9\xb6:\xade\xf9\u007fW\xad\x8d\xabuz\x1e\xe5zkE\v7\xb5*\xf1\x89\xe6\xcd\xcdJz\xb8\xea\xb6\x02f\xed\xa8Sl\xfb\x95\x9e\x8c\xbfH\x9b\xf2\xaeӧP?\xac!\xe8X\xa9Ō_\xc1\xdf5|\xa2ޖ\xb2\x93\x98\x13\xdfv\xcc\x00\xa4\x03m\x0et\xbcC/\x92\x00\xa3S\xbe\xa6n\x8di\x91\x9b\xe1\xb8t\x90JQƶX\x9b\xfdhƦBӢ:\x02sd:\xfb\xdfT\x1f\xaaw\xbfZ\x17\xa4\x98\xf3\xd4Ԡ\xf8\x8a{9|\xe5\x19\xa2{?8Q\x1c\xff\xe4\x0e\xf4\xe3\xc7\xd2,\xcfl\xde\xf6\xe3\b\x18\x1b\xa9\xa8\x16\x1c\x89\x13m\xc50|\x8f\xfc\xb8\xba\xbfs\xb1\x84G\xed\xc7ʾ\x03Z\x8c\x1d\x13\n\xaa\xe2M~\x97\bΣ\x1d1\x80\x93\xf6\xa2\xceA\x19\xbd\xed9N\x1a\xf9\x95\x82*\xb4dPƂ@O\xa9Io\x81\xef\x98\xdeb\xfb\n\x95\xf9\u007f\x9dS2\x9f\x9eʹ\x16\"\xf5%\xf3\xb8I\xa3Or\xacL\x1f\xbc\x00\xb7\x9b\xc7_\u007f\v\xf7E\xb3\x17ۜ+\xb8\x0f\xf6\x97,M\xa0N}\xfb\"\u070eooo\x87\xcf\xcd7 \xf1ַ\xf0W\xde5\xe0\xc0\\\xfb*\xfe\xeb\xe1PS\xb5z\xb5\x04\xfe\x92v\xa5\xe7\xc3|\x04\xd8\xda\x04\xff\x9agލ\x19t~\xee\u007f\v\x8f\xf1#Ƶ\"\x83\xf6\x14\x8d\xf0`\xa9\x95l_\xc5bP\x18\xcb-\xb7?/-z\xdfZ\xbak\xc3/17\xc85\x9ak\a\x93)_v\xf4\x9aA\xee΄\xf5\xe9\xa5x\x0e\xff\xfeϤMה\x13\x1b\x8f\xe2\x87\xfeǵw)d\x94/d\xf1'\xa7:&}\x1d\x84\xbf\xfdc\x92\xaeB\xf1\\>i\xd1\xe4\u007f\x03\x00\x00\xff\xff\x1d\r\x93\v\x97\x1c\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4\x96Ms\xe36\x0f\xc7\xef\xfa\x14\x98}\x0e{y$\xefN\x0f\xed\xe8\xd6\xcd\xee!\xd36\xe3I2\xb9tz\xa0I\xd8\xe2F\"Y\x00t\xeav\xfa\xdd;$%\xbf\xc8v6=\x947\x91 \xf0\xe7\x0f\x04Ī\xae\xebJ\x05\xfb\x84\xc4ֻ\x16T\xb0\xf8\x87\xa0K_\xdc<\xff\xc0\x8d\xf5\x8b\xed\xc7\xea\xd9:\xd3\xc2Md\xf1\xc3=\xb2\x8f\xa4\xf13\xae\xad\xb3b\xbd\xab\x06\x14e\x94\xa8\xb6\x02P\xceyQi\x9a\xd3'\x80\xf6N\xc8\xf7=R\xbdA\xd7<\xc7\x15\xae\xa2\xed\rRv>\x85\xde~h\xbeo>T\x00\x9a0o\u007f\xb4\x03\xb2\xa8!\xb4\xe0b\xdfW\x00N\r\u0602\xc1\x1e\x05WJ?\xc7@\xf8{D\x16n\xb6\xd8#\xf9\xc6\xfa\x8a\x03\xea\x14xC>\x86\x16\x0e\ve\xff(\xaa\x1c\xe8sv\xf5)\xbb\xba/\xae\xf2joY~\xbaf\xf1\xb3\x1d\xadB\x1fI\xf5\x97\x05e\x03\xb6n\x13{E\x17M*\x00\xd6>`\vwIVP\x1aM\x050\xf2\xc82kP\xc6dª_\x92u\x82t\xe3\xfb8Ldk0Țl\x90L\xf0\xb1\xc3|D\xf0k\x90\x0e\xa1\x84\x03\xf1\xb0\xc2Q\x81\xc9\xfb\x00\xbe\xb2wK%]\vM\xe2\xd5\x14\xd3$d4(\xa8?ͧe\x97\x04\xb3\x90u\x9bk\x12X\x94D\x9eD\xe4\xb8\xd6;\xa0#\xbe\xa7\x02\xb2}\x13:ŧ\xd1\x1f\xf2µ\xc8\xc5f\xfb\xb1\x90\xd6\x1d\x0e\xaa\x1dm}@\xf7\xe3\xf2\xf6黇\x93i8\xd5z!\xb5`\x19Ԥ4\x81+\xd4\xc0;\x04O0x\x9a\xa8r\xb3w\x1a\xc8\a$\xb1\xd3\xd5*㨪\x8efg\x12\xde'\x95\xc5\nL*'\xe4\fm\xbc\x04hƃ\x15\x98\x96\x810\x102\xbaR`'\x8e!\x19)\a~\xf5\x15\xb54\xf0\x80\x94\xdc\x00w>\xf6&U\xe1\x16I\x80P\xfb\x8d\xb3\u007f\xee}s:g\n\xda+9\xe4g\x1a\xf9\xd29\xd5\xc3V\xf5\x11\xff\x0f\xca\x19\x18\xd4\x0e\bS\x14\x88\xee\xc8_6\xe1\x06~I\x98\xac[\xfb\x16:\x91\xc0\xedb\xb1\xb12u\x13\xed\x87!:+\xbbEn\fv\x15\xc5\x13/\fn\xb1_\xb0\xddԊtg\x05\xb5D\u0085\n\xb6\xce\xd2]\xee(\xcd`\xfeGc\xff\xe1\xf7'Z\xcf.H\x19\xb9\xd0_\xc9@*\xf3\x92\xf6\xb2\xb5\x9c\xe2\x00:M%:\xf7_\x1e\x1ea\n\x9d\x931\xa7\x9f\xb9\x1f6\xf2!\x05\t\x98uk\xa4\x92\xc45\xf9!\xfbDg\x82\xb7N\xf2\x87\xee-\xba9~\x8e\xab\xc1\nOW2媁\x9b\xdcbSQ\xc7`\x94\xa0i\xe0\xd6\xc1\x8d\x1a\xb0\xbfQ\x8c\xffy\x02\x12i\xae\x13ط\xa5\xe0\xf8\xef07.Ԏ\x16\xa6\xf6}%_\x17\x8a\xf6!\xa0N\x19L\x10\xd3n\xbb\xb6:\x97\a\xac=\xc1Kgu7\x15\xed\x8c\xee\xbe\xc0\x9b\x93\x85\xcb\x05\x9dơM\xceW\xae\x1e\x1er\xee,\xe1\xec\x16\xd6p\xd6s_璛\xe1\xbf$S:\xf1\xc8FG\"trԟեMoe\x81D\x9e\xcefg\xa2\xbed\xa3\xfc\x04P\xd61(\xb7\x1b7\x82tJ\xe0\x05)\x95\x81\xf61\xf5\x194`\xe2\x19\xbf\x11\xcb\xf1\xbf$\x90\xd7\xc8ܜ\xd9Y\xc1ႦW\xb2\x93Fz^\xa8U\x8f-\bE\xbc\x92YE\xa4v\xb3\xb5\xfc\xcf\xfa\x06\x82e\xb2\xb9\x94\x83\xfd\u007f\xfa\x9bIȸ]\x1c\xce#\xd5p\x87/\x17foݒ\xfc\x86\x90\xe7W>-.\v\xbd\xfdc\xe0\r\x94.^ʳIN\xfd\xce\x1cQd\xf1\xa46\xc7\\9\xae\xf6\xfd\xbb\x85\xbf\xfe\xae\x0e\xf7Zi\x8dA\xd0\xdc\xcd_i\xefޝ<\xb7\xf2\xa7\xf6\xae\xbc\x8c\xb8\x85_\u007f\xabJ(4O\xd3\xeb)M\xfe\x13\x00\x00\xff\xff--\nM\xde\n\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4WO\x93ܦ\x13\xbdϧ\xe8\xf2\xef\xe0_\xaa,\x8d]9$5\xb7d\xed\xc3V\x1cǵ\xeb\xec%\x95\x03\x83z$\xb2\b\b\xdd\xccz\xf3\xe9S\r\xd2\xfc\xd1hfLJp\x134\xcd\xe3\xf1\xfa\x81\x16UU-T0\x0f\x18\xc9x\xb7\x02\x15\f~et\xf2E\xf5\xe3\x8fT\x1b\xbfܾ[<\x1a\u05ec\xe0&\x11\xfb\xfe\x0eɧ\xa8\xf1=n\x8c3l\xbc[\xf4ȪQ\xacV\v\x00\xe5\x9cg%\xdd$\x9f\x00\xda;\x8e\xdeZ\x8cU\x8b\xae~Lk\\'c\x1b\x8c9\xf9\xb8\xf4\xf6m\xfdC\xfdv\x01\xa0#\xe6\xe9_L\x8fĪ\x0f+p\xc9\xda\x05\x80S=\xae\xa0\xf1O\xcez\xd5D\xfc;!1\xd5[\xb4\x18}m\xfc\x82\x02jY\xb4\x8d>\x85\x15\xec\a\xca\xdc\x01P\xd9\xcc\xfb!\xcd]I\x93G\xac!\xfeen\xf4\xa3\x19\"\x82MQ\xd9S\x10y\x90\x8ck\x93U\xf1dx\x01@\xda\a\\\xc1'\x81\x11\x94\xc6f\x010\xec=ê\x86\xddmߕT\xba\xc3^\x15\xbc\x00>\xa0\xfb\xe9\xf3\xed\xc3\xf7\xf7G\xdd\x00\r\x92\x8e&pfp\x82\x19\f\x81\x82\x01\x01\xb0߁\x02\xe5@E6\x1b\xa5\x196\xd1\xf7\xb0V\xfa1\x85]V\x00\xbf\xfe\v5\x03\xb1\x8f\xaa\xc57@Iw\xa0$_\t\x05\xeb[\xd8\x18\x8b\xf5nR\x88>`d3\xb2\\ځ\xb8\x0ez'\xc0_\xcb\xdeJ\x144\xa2*$\xe0\x0eG~\xb0\x19\xe8\x00\xbf\x01\xee\fA\xc4\x10\x91\xd0\x15\x9d\x1d%\x06\tRn\xd8A\r\xf7\x18%\rP\xe7\x93mD\x8c[\x8c\f\x11\xb5o\x9d\xf9g\x97\x9b\x84!Y\xd4*\x1e\xe5\xb0o\xc61F\xa7,l\x95M\xf8\x06\x94k\xa0W\xcf\x101\xf3\x94\xdcA\xbe\x1cB5\xfc\xea#\x82q\x1b\xbf\x82\x8e9\xd0j\xb9l\r\x8fE\xa5}\xdf'g\xf8y\x99\xebì\x13\xfbH\xcb\x06\xb7h\x97d\xdaJE\xdd\x19F\xcd)\xe2R\x05Se\xe8.\x17V\xdd7\xff\x8bC\x19\xd2\xeb#\xac\xfc,2#\x8eƵ\a\x03Y\xf3\x17N@T_\x04S\xa6\x96]쉖.a\xe7\xee\xc3\xfd\x17\x18\x97·1e\xbf(g7\x91\xf6G \x84\x19\xb7\xc1X\x0e1+Or\xa2k\x827\x8e\xf3\x87\xb6\x06ݔ~J\xeb\xde0\x8db\x96\xb3\xaa\xe1&;\r\xac\x11Rh\x14cSí\x83\x1bգ\xbdQ\x84\xff\xf9\x01\b\xd3T\t\xb1\xd7\x1d\xc1\xa1IN\x83\vk\a\x03\xa3\x93\x9d9\xafI\xa9\xdf\a\xd4rzB\xa0\xcc4\x1b\xa3si\xc0\xc6GP\xfb\xca\x1f\b\xac\x8f2\xcfWn\x06\xa7b\x8b<\xed\x9d`\xf9\x92\x83d\xf9\xa7N\x1d\x1b\xcd\xff\xb1nk\xf1\n\x1a\x80\x14\xf7\xf8\xae>\xc9x\x1e\x03̪w\x16\xc9(b\xa1Ax\x15+\x10\x93:\xc4t\xba\xb44t\xa9\x9f_\xa0\x82\x9f3揾\xbd8~\xe3\x1d\x8b\xdc/\x06=x\x9bz\xbcw*P\xe7_\x88\xbde\xec\u007f\v\x18\xcbUz1t\xbc\x91w\xb7ԅ\xc0dϮ{\x87\xe2\xf7x~\xa7C\xc0UY\xae\xc04D^\xb5ћ\xfb\xdbo\xa1\xf0L\xf8\xc5C:S\xb6c\xcb\xd7\xf3\xcb\x1a\x94\v~ԠL)w\x16\x82<{\xa2CF\xda\xdb\xe7\x93\xe1n6#\xc0Sgt\x97'f\x01\x8b3\x13ym\xb2\xcf};|\xa9{\x13q\xa6\x88\xaa\\\\3\xdd\x02\xfe\xa4\xfb\x8c[\x9d[\xa0\x1a\x1c\xe4*\xc7cʼn\xbe\xc1\xf3r\xfcH\xb5N1\xa2\xe3!K~\x03L'\\kz\xa3S\xfc~\xf7\xf1\x05\xe7{\xbf\x8f̯\\e\\A\x13\"VdZy\xb9Șx_\xf6\xa4S2J;~I\x1d\x135{\xa2\xf85\x98R0/@\xfc\xb0\v,\x06\x8d\xae\\\xbeӷbN\x88\x94\x1f6ZM\x9fT\xd2\xd6\b\rZdl`\xfd\\n\x9agb\xecOqo|\xec\x15\xaf@.\xe5\x8a͌\x8c\xe4=\xaf\xd6\x16W\xc01\x9dS\xd9\xec\xc6C\xa7h\xa6\f\x8f\xf6\xfcYb愱+Ƌʀ\xb3\xf7A\x05\x9f\xf0i\xa6\xf7s\xf4\x1a\x89\xf0\xb4\x8c\xce\xeed\xb6\bN:I^N\xcd\x01KÃ|\xe8ٗ\x8c\xd2\x1a\x03c\xf3i\xfa\x97\xf3\xea\xd5\xd1oK\xfe\xd4\xde5\xa6\xfc\xa0\xc1\x1f\u007f.JVl\x1eƿ\x11\xe9\xfc7\x00\x00\xff\xff:@\xbd\xf3\x1a\x0e\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4Z\xdds\x1b\xb7\x11\u007f\xe7_\xb1\xe3<\xa8\x991\x8f\x89\xdbi;|s\xa4\xa6\xa36\x915\x96\xad\x17\x8f\x1f\xc0\xc3\xf2\x0e\xd1\x1d\x80\x028\xcal&\xff{g\xf1q\xbc\x0f\x90\x944ur/6\xf1\xb1\xf8a\xbfw\xa1\xc5r\xb9\\0-\xee\xd1X\xa1\xe4\x1a\x98\x16\xf8š\xa4_\xb6x\xf8\xbb-\x84Z\xed\xbe_<\b\xc9\xd7p\xd9Y\xa7\xda\xf7hUgJ\xbc\u00ad\x90\xc2\t%\x17-:ƙc\xeb\x05\x00\x93R9FÖ~\x02\x94J:\xa3\x9a\x06ͲBY\xf38\xfa\x01\xed\xe4\xfa\x8b\x99\xdb\x1e\xd1~[aޞ\xc3\xf4\xee\xfb\xe0@\xcb\x1a[\xb6\x8e+\x95F\xf9\xf6\xf6\xfa\xfe\xcfw\xa3a\x00m\x94F\xe3Dr\xe8\xe1\x1bı\xc1(\x8cY}A\x04\xc3*\xe0\x14\xc0\xd0\x06\xab\bc\xc8#\x86 \x0eaIu\rZ\x94nȒ\xf4\xa9-0\tj\xf3\v\x96\xae\x80;4D&\t\xa6Tr\x87Ɓ\xc1RUR\xfc\xb7\xa7mI\xd7\xe8І9\x8cq\xe5\xf0y\xd7/Y\x03;\xd6t\xf8\x1a\x98\xe4в=\x18\xa4S\xa0\x93\x03z~\x89-\xe0ge\x10\x84ܪ5\xd4\xcei\xbb^\xad*\xe1R\xfc.U\xdbvR\xb8\xfdʇb\xb1\xe9\x9c2v\xc5q\x87\xcdʊj\xc9LY\v\x87\xa5\xeb\f\xae\x98\x16K\x0f]\xfa\x18^\xb4\xfc\x1b\x13#\xbe\xbd\x18a\x9d)F\xf8|x=!\x01\n\xb0 ,\xb0\xb85\xdc\xe2\xc0\xe8\xe4 \xdf\xff\xe3\xee\x03\xa4\xa3\xbd0\xa6\xdc\xf7|?l\xb4\a\x11\x10Ä\xdcbt0[\xa3ZO\x13%\xd7JH\xe7\u007f\x94\x8d@9e\xbf\xed6\xadp$\xf7\xffth\x1dɪ\x80K\x9fԐ\xc3\xec4i./\xe0Z\xc2%k\xb1\xb9d\x16\xbf\xba\x00\x88\xd3vI\x8c}\x9a\b\x86\xf9\xd8tq\xe0\xda`\"%MG\xe45Ʉ\xee4\x96$=b \xed\x14[\x11=\x14\xb9s6]^\x8c\b\xe7\r\x97\xbe\xacw\x9a.\x82\\p\x99\xecI\xd8\xe4\xc0\xa7&\x87\x19VΈ\x024S/\xdb\xef\x19F.\x1b\x1dl1\xa3pD\f\xf4I\xc5\xf1\xcc=n\x14\xc7\x1cl\xda\n\xaefA[)\xe3#\u007f\xd4I9?\x85>%\x9f\x05L+~\x06W<\x91\x81\xc1-\x1a\x94%&\xc7u*\x9d\xc9 \x1b&\x1as\x8cǕ\x02Nx\xf5,ⷷ\xd7ɓ'&F\xecn~\xee\x19\xfeз\x15\xd8p\x1f\xe8Ο}q\xbd\r\x87y\x9f\xe6\x140\xd0\x02Cb\xda\a\t\x10\xd2:d\x1c\xd46K\x91\xca' \xc37\x18w\xbc\x0e\x1e,\xba\xcaCh!\xde\x03#\xdf)8\xfc\xeb\xee\xdd\xcd\xea\x9f9\xd6\xf7\xb7\x00V\x96h}^\xee\xb0E\xe9^\xf7\xa5\x02G+\frJ\xfc\xb1h\x99\x14[\xb4\xae\x88g\xa0\xb1\x9f\xde|\xces\x0f\xe0Ge\x00\xbf\xb0V7\xf8\x1aD\xe0x\uf593\xd2\b\x1b\xd8\xd1S\x84G\xe1j1\r\xa6=\aH\xbd\xe2\xb5\x1f\xfdu\x1d{@P\xf1\xba\x1dB#\x1ep\r\xaf|Zs\x80\xf9+\xd9\xceo\xaf\x8eP\xfdS0\xedW\xb4\xe8U\x00\xd7\xc7\xe1\xa1\xd1\x1d@\x06\xcb3\xa2\xaa\xf0\x90UM?\x1fT\xc8U\u007f\v\xca\x10\a\xa4\x1a\x90\xf0\x84Iz\xc1Q\"\x9f\x81\xfe\xf4\xe6\xf3Q\xc4c~\x81\x90\x1c\xbf\xc0\x1b\x10\xb1\xd8Ҋ\u007f[\xc0\a\xaf\x1d{\xe9\xd8\x17:\xa9\xac\x95\xc5c\x9cU\xb2ه\xf6\x881\tʄyp\xcdL\ueffa*\x13C;C\x88\xf6\xcb\xd8\xf6[2\xc9\xe9\xffVXG\xe3/\xe2`'\x9ed\xbe\x1f\xaf\xaf~\x1f\x05\xefċl\xf5H\x02\x1etd\xd8\xe58\x93\x98\xbd\x1f-N\xa9c&c\xed\xd7<+3t\xacʤb\xc3\xf6䩄\xed$\aƭ\x18VY`\x06\x81A\xcb4I\xee\x01\xf7\xcb\x10\xe25\x13\x14\x9f)\x04\xf7}\x0e`Z7\"\x1b\x8ac \x8fIh\xe4\x04\x15ڬ\xb2\xc7\ue795ð\xafsF\n\x1f\aK\x93\f\xcet\x96\\\x9d\xb3\xd4Q\xbfi\x8e\x16e\xd7Ρ,\xe1Ai\xc12\xe3\x06\xad\x13ef\xe2\xd5<\xd38!\xac\xc0\xcb3<\x88-\xe8L\xf1\x12E\x112\xbd\xbe\x80\xf1]\xc7\\\x85p\xbc<8\n\x91*t\xca[\xc7\x10\x97\xf9Rr\xb2\x86J\xabɐV|1ed\xa6\xf3\x98&G\x9d\xd1!\xd2y}\xed\x1b\xdeϨ\xb0C#?\xf24\xf8S\x97\xda\xfbTL\xbc\xb4\xc6.\x15\xe5\xe9㧕\xd3⽜\xef\xf0\xed,ã\xba\x8b\x96\xacw\xd0\xf6\x8fg\xe4\x8ad\x18\x90\v;}\x04#j\xc8}\x12M9\xfe\x96\x89\x069\xa4\xb7\x9d\xe9\x9e\f\xd5!\x95\rn\xc9\xdd\a\xd3K\xa5i\x84\xd7'\xaa5\x82\xf5}\xa2\v{\x82fg\x91\xfb\x9eF\x86\t\xf3\xe4u\xabL\xcb\\\xe8k.\xb3De\xd74l\xd3\xe0\x1a\x9c\xe9\xe6\xd3',\xb1EkYu\xce\x14\u007f\x0e\xabB\xc5\x1e\xb7\x00ۨ\xce\xf5%\xfb\xc8=^بS\xcf\xeb\x1ad\x8b\xe1\xb1:3*VlLڛ\xc6\xef\x19:\x82Ã\xa0G\xb5\xc1|\xd0\u007f\x89O\x00\xf0\x0fZ\xe7\x10Қ\x9c\x81\xf5\xde뤅\xc1\t\xa7|\x83\x8f\x99\xd1\xd9C\xdcp\xf22\x99Lf\xeeGo\rϺ\u007f<\xe8\x1c\v\xe22\xa8U\x93\x8cY9ր\xec\xda\r\x1a\xe2\xc3f\xefЎ\xddy\xae?\xe3\xeb\xba\x03\x1b\a\xfb\x93\xfc\x02\xa5X\xaa\x96L\xfa>*Y\x97S\xc0\x85\xd5\r\xdbg\b\xa7\x8b\xf8܍\x8c\x8b\\\xc0A\x9f\x93Qk4~\xea\xb9}%\x8f\xe9J\xc9#\x95F\xb2g!\xdd_\xffr\"\xd3\x13\xd2a5\t\x0eq\x9e\xd8\xf9\x03\x9d\xf2uN8\x91\xc4Xɴ\xad\x95\xbb\xbe:\xa3\x05w\xfd\xc2d\r\xb3\xe79\xec\xa9EUȉ\xaa\xf7-\xcf2\xd5\xf1\x13\xf09\xa8\xa3\xc5g\xa2P||\xceŠ;\xd4̐\xa5\xfb7\x81\xcb\xe9\xa3\xd5k\xb0\xc27:)\xf3\f\xa9hhCX\nN\x94Z)\x83\x19\x97\t\xf3\xb02\n\"c\xf8\xbfg\xfc\xc8\xea\xc9l\xd0#\xe7\x03ڱY>\x1c\xe96\xfdC\xd0\x1a~\xfdmqHlXI\xc5\x13\xf2\x9b\xe9\x1fYĔ3\xfdՄ\xffY*\x19*\t\xbb\x86O\x9f\x17\xe9\xd9\xf2>\xfd1\x04\r\xfe/\x00\x00\xff\xff\xb0\xddǼ\x99\"\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4YKs\x1b\xb9\x11\xbe\xf3Wti\x0f\xcaV\x99\xc3]'\x95\xa4x\xb3\xa5lJɮ\xac2e]\\>\x80\x83\xe6\f\x963\x00\x02`H3[\xfb\xdfS\x8d\a9/\x92\xa2*Z\xcf\xc5\x16\xd0h|\xf8\xd0/4'\xd3\xe9t´xBc\x85\x92s`Z\xe0W\x87\x92\xfe\xb2\xd9\xfa\xef6\x13j\xb6\xf9q\xb2\x16\x92\xcfᦱN\xd5\x1fѪ\xc6\xe4x\x8b+!\x85\x13JNjt\x8c3\xc7\xe6\x13\x00&\xa5r\x8c\x86-\xfd\t\x90+錪*4\xd3\x02e\xb6n\x96\xb8lD\xc5\xd1x\xe5i\xeb\xcd\x0f\xd9߲\x1f&\x00\xb9A\xbf\xfcQ\xd4h\x1d\xab\xf5\x1cdSU\x13\x00\xc9j\x9c\x83V|\xa3\xaa\xa6F\x83\xd6)\x836\xdb`\x85FeBM\xacƜv-\x8cj\xf4\x1c\x0e\x13aqD\x14N\xf3\xa0\xf8\x93\xd7\xf31\xe8\xf1S\x95\xb0\xeeߣ\xd3?\v뼈\xae\x1aê\x11\x1c~\xd6\nY4\x153\xc3\xf9\t\x80͕\xc69\xdc\x13\x14\xcdr\xe4\x13\x80H\x80\x876\x05ƹ\xa7\x94U\x0fFH\x87\xe6\x86T$*\xa7\xc0\xd1\xe6Fh\xe7)\xdb\xeb\x01\xb5\x02W\"m\xe9\xe9fB\nY\xf8\xa1\x00\x01\x9c\x82%BD½2\x80_\xad\x92\x0f̕sȈ\xb8L+\x9eɤ3\xca\x04\xce\xef{\xa3nG\xe7\xb0\xce\bY\x1cC\xf6\u007f\x06\xd5\xc1\xf3\xa0\xf83\x91<\x96\xe8e\x12\x9aFW\x8aq4\xb4y\xc9$\xaf\x10\xc8r\xc1\x19&\xed\n\xcd\x11\x14i\xd9\xe3Nw\x91|J\xfaZ3\x97\xb0s\t\x15A\xb6\xb3\xfdS{\xe8ܾ\x0f\x8a\xc7\x05\x10\x8d\x1a\xacc\xae\xb1`\x9b\xbc\x04f\xe1\x1e\xb7\xb3;\xf9`Ta\xd0\xda\x11\x18^<\xd3%\xb3]\x1c\v?\xf1\xba8V\xca\xd4\xcc\xcdAH\xf7\u05ff\x1c\xc7\x16\x17eN9V\xbd\xdf9\xb4\x1d\xa4\x8f\xfdဖ\x9c\xad\x88\xd7\xffM\xe0.\tҭ\x92]^\xdf\xf7F\xc7\xc0\xb6\x94\xa6@\x9c\r\x82hG뻢\xab\x8f3\x17\x06\xc2\xf4\xe6\xc7\x10\xca\xf2\x12k6\x8f\x92J\xa3|\xf7p\xf7\xf4\xe7Eg\x18@\x1b\xa5\xd18\x91\xa2k\xf8ZY\xa55\n]f\xafIa\x90\x02N\xe9\x04mp\x8a0\x86\xa3f5\xff\xce\xc4\xfck\xaf;X\aN\x17>\x9f\xebN\xdc\x00%;\x10\x16X\\\x1aNq :\x85\xec\x8f\xffX\xdc\xcf\xfe9\xc6\xfc\xfe\x14\xc0\xf2\x1c\xad\xf5\xf9\x1ak\x94\xee\xcd>gs\xb4\xc2 \xa7\xc2\x05\xb3\x9aI\xb1B벸\a\x1a\xfb\xf9\xed\x97q\xf6\x00~R\x06\xf0+\xabu\x85o@\x04\xc6\xf7\xe1/ٌ\xb0\x81\x8e\xbdF\xd8\nW\x8a~\xd2\xda3@\xd6\x15\x8f\xbd\xf5\xc7ul\x8d\xa0\xe2q\x1b\x84J\xacq\x0eW\xbe\x12<\xc0\xfc\x8d\x1c\xeb\xf7\xab#Z\xff\x14\x1c芄\xae\x02\xb8}\xbek{\xe4\x01\xa4+\x99\x03gDQ\xe0\xa1\x10\xed\u007f>xSH\xfc\x1e\x94!\x06\xa4j\xa9\xf0\x8a\xe9\xf6B\x00\xfd\xf9헣\x88\xbb|\x81\x90\x1c\xbf\xc2[\x102p\xa3\x15\xff>\x83Go\x1d;\xe9\xd8W\xda)/\x95\xc5c\xcc*Y\xedB\xb5\xbfA\xb0\xaaF\xd8bUMC\xbd\xc1a\xcbv\xc4B\xba8\xb27\x06\x9a\x19w\xd2ZS\x95\xf1\xf8\xe1\xf6\xc3< #\x83*|\xbc\xa3\xec\xb4\x12T5P\xb9\x10r\x9e\xb7\xc6A\xd2L\x9fm\x82\xf98\x05y\xc9d\x81\xe1\xbc\b\xab\x86\xb2Pv\xfd\x12?\x1e\xa6\xfe\xf4\x8d\x94\x00\xfd\xc0\xf1͒\xe83\x0f\xe7+\xd5g\x1c\xae\xfd\xd6:y\xb8u\xb3D#ѡ?\x1fW\xb9\xa5\xa3娝\x9d\xa9\r\x9a\x8d\xc0\xedl\xab\xccZ\xc8bJ\xa69\r6`g\xfe\xc9<\xfb\xce\xff\xf3\xe2\xb3\xf8\xd7\xf5s\x0f\xd4y\xf4\xbf\xe6\xa9h\x1f;{ѡR\xad\xf8\xfc2q5\xacTN0\x11\f\xe0\f\a\xb1\x994\xf22\x8a\xf6\x13*E?B\xaf\x11oE\xe3!\xf6R\xbb\xa2\x874\x95\xbd]\x84\xd3\xf1\xf7^OF+>\xe9\x93\xd6v\xc9\xde\xe4\xc1\xa1\xfa\x13][\xed\xcdv\x9a\x9c\xed\xd3\f\x9fʾ\x83v\xc9c9t\xed\"\xef!f\xbb\xd4ˣ\aˋ\x9f˹\xa2\xc7@\xf7W\x8b\xd36p3\\\xe1{S\x86G\x9f\x105\xfa7hh8n\x99M\x9b\x8c\xdd7\xb4\xf4\x85\xa5>O\x92:\xe4\xbeT\xa7\x97Ċ\x89\n9\xec\u007f7\xf1\xcdq\xeb\x9b4\xd7c\x95iR\xd4X\xe4>n\x8c\x80\x1e\xaeK}O\xce\x1cNI\xc5@B6UŖ\x15\xce\xc1\x99f8}½j\xb4\x96\x15\xe7\xfc\xeb\x97 \x15^\xf1q\t\xb0\xa5j\xdc\xfe\x19\x1f\x1d-Rqm\xa3\x15\\\xd6J(\x99=\a\xe5\x81d\xc6,n\xef\xf2\xa7M\x0eN\x84\xb2{\u070e\x8c\x0e\xfa\xd0\xedɛdB#s?y븈\x80\xb8\xd19\x0e\xa2\x18\x94\xaaJ֭\x1c%\xa5\xa6^\xa2!\"|\xf3;1\x92\x02\xc7X_Ŀ\xa7\x0eL\x1e4\xa4X\x18T\xc5\x17bΤo\x13\x92\xfd:\x05\\X]\xb1݈\xdet\x12_2\x91\xf9\x92\x1f\x1d,&y!\xb9\xbf\x9f\xbb\xb4\x9f\xb3o\xee\x8f\x17tc?\x15\x8c\xddB\xbb\xefߛ\xdf\xff\xaa\xf1:;\x9c(\xe2\xacc\xc6=7\xec-:\xc2\xe7\"\x9eW=\x1e\xefڡk\x18\xa8\xba\xdb\xfc\x911j\x94\xa8\xc1\xa0G\xce[\xbac/\xb4=\xd2,\xf7\x9d\xfe9\xfc\xf6\xfb\xe4\x90\xeeXNU;\xf2\xfb\xfeOڱVI\xbfP\xfb?s%\xc3O\xcav\x0e\x9f\xbfL 6M\x9f\xd2\xcf\xce4\xf8\xbf\x00\x00\x00\xff\xffe\xe5\xd5&\b \x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xdc:\xa5\x02\x1b\x84\xa6.\x99\xc5r\r\xf7\x12>\xb2\n\xc5Gf\xf0\xea\f J\x9b\x15\x116\x8f\x05}}x:\xd8S\xad\xf7GT^\x13\xfc\n\xa7\xff\xb1\xc6bpbh\x1a߆c\x0e[\xa5\aʁ\xa6\xac\a@Ӈ\x96\x1e\u007f\xfaI\x83\x9d\xfes\xb2\x95\xffh\a\x92\xfc\xd0&\x1a\xc9\u007fmЩ8\u007fbq\xa4RF !\xeeω\xc5z\xf4\xff\x04M\xe9\xc1\x1f\x85hJ,[m;\xc2\xe5dǟF\x13\x9c9b\\\x92\xfc\x93\xfa\xa7m\xcb\xee_R\xa7\x89\x1d3\x8d@\x12ȥ\x87\a\\:d\x93\x94\xa6\x87[\xac\x12\x9b\x9b\xc5\x0e\x9c\x9dc\x1b\x81w`u\x83\x13\x94aZ\xb3\xe3\x04a\xa2mΥK;>(\x04\xc1\v\xec\x1b\nO\x1aod\x98\x1e\xef\b~\xe7T\xe1\x86\xd4Y\xc4\xf2A\t^\x1c\x17I\x93\x9a\x14\x8f[8|Q\x827\xb8g\a\xae\x1a\x9d\xc0\x89\x8e$\x8d}\xea,i\xa7M\x15)\xb3\x00\xa5\xbc\f\xe3$\xb5\xf6J=-1\xff\xcf4\xa6S\xdbP8\xb7.\xe2\xa2\x03\xbb\x83\x15\xdd \xe0\x0f,\x1a\x9b\xd8&@\xd98\v\xa24\xd4\xca\xd8i\xc6O+\x1f\xf0\xfa`JjaNjF\x98\x05]\x19YG\x88\x0e\xf4\xa6\x92H{\xad\x88u\xddX\xad\x1a?\xf6\xd4\xc0\xf5(\x9e\xa6\bl\x98\xc1\x12T\x10\xfbF\xa0\tk\x95\x8e\xfd\x9db\xb9\x9d\x04\xdd\"\xef]\r\xc16(\xc0\xa0\xc0\xc2*=\xa6d\x0e=\xfd\x93\xa3,'\xe8\x98P\x9bC\xf9\xef\x10\x9b\x01\t$\xe6\xcf{^\xec\xbd\x17@\xb2\xe9\xe0@\xa9\xd08\xcdA\x9e\xeaq\nIX\xe2}XdNwt\xcf\u0099:\x85\x97\xd2'ݓ\xa1o\xbbgA\xf3\x8e4Kx\x9f4\x9d\xdd\xf3\xff\x93\xb0є\\ \xb4\xf7\xa3\xa9\xaf+\xb4.\xaa\"o\xff~\vX\xd5\xf6x\v\xdcƷK\x10\x99\x10\xbd\xf5\xff\xc0\x8c9_\xe2\xefOg\xbe\xaa\xc4\xcfre\t\"q\xa5]\xfe\x0f\xc8\x14g,\x1e\x83\xad\xc8f\xc8_\xfb\xb3n\x81o[\x86\x94\xb7\xb0\xe5¢>\xe1̋\xce\xcbk\x10#\xc7\xde\xd1S1[\xec?\xfd \xcf\xc6t\x19\xa8L\xba\x9cN\xf6>q\f\x12\x86\x86y\x01.\xb8\xf8\x95k\xac|\\\xfc\xcdQ\xb3{\xe3\x02\x8a\x0f\x9f\u007f\xc2r\x8e<\x90'y#D>\x9cl\xb6\xbftp\xf4s\xd1\b\xaeO\x1b4\xf9\x8c\xc7-0x£\xf7X\x98\x04b\x0e\xb3\xce\xdfM\x86Oc\xe2\xb8ԋw\x8f\xf1\xe8\xc0\x84\\\xca\xe2\xec\\Q\xf0\xcf\x13&\xfc\xfd\xd43 \xed)D\xb8\x9e\x92\xf4\xc2\x11\xc2E\xde\xf9\xc4\x03\x97\x17\x8b\xbah\x199\xc8W$\U00049d3f\x00͖m\xbd\xfc\xa1c\xec[\xe3YD\xa7`\xcf\xebLD]\xfaР;-13\xf6\x9d\t^\xb6\vy\xb9\xbf\x97\xd3\xde\xf0\xf0\xf9\xac콼\xf5!\x99qR\xf2\x93B\xf3YY\xf7\xe6*\xe4\xf4\x1b\xbf\x80\x98~\xa2;^ҫm\xa2C?Ŗ!\xdc\xfe\xb9\xf7\x99\x94\x96=\xdc\xc0\xbd\xa4\xc0%\xd0\xc3%L\xfdr\xf3\xf6a\xf8T\x8dq94\xa9\xe4ʙ\xcauj%O\xecL\x90J\x0f82\xdeZ\xbb\xa8_0\x13\xec7\xb2$~\xbeO\x01\vV`\x19\xa3M\x97\xb8d\x16w\xbc\x80\n\xf5n\xcep\xf4\x9f\x9a\xf4{\xde\x162\xb5\xae\u007fΔ\xb0<\xd3\x1e\x9f\xa0\xba\xcb\xe5ͬ\xe8\xe4f\x8c\x8a\xcc^\x1c:\x91\xaf\x9c\x1e\xba\x8c\x913\xb1\xce\xffX\xa4.+KW\\b\xe2\xe1\f\x8d\u007f\x06/ƶ\xdfo\xcc[Ȋ\xd5t~\xff\x87̜\x13\xe8\xff\x85\x9aq\x9dq\x86?\xb8:\x91\xc0\xc1ܐ\x19\xeb/C+p\x03\xc4\xdf\x03\x13\xe3Lx\x029E\xba\x05\x857\xe4j;\xf2Xn\xe1y\xaf\x8c\xb7\xa9[\x8e\"\x95\xb2\x19>\xdc\xc0\x9b'<\xbe\xb9\x1d\xe9\x817\xf7\xf2\x8d7\xf0g\xab\x9b\xd6[PR\x1c\u135b\xfb\xe6%NP\xa6$f\r\x93\xc9\"\xaf\xed\xd5\x16\xaa\xaa\xd8i\x95/k\xab\x1f\xfd\xcc(\xd3\x01\x90\xe7\xbe\xde5\xee\\\xe6\xbb{Q\x86\\}\xef\x99\xdb=\x97\xc0\xe2\xf1G\x1d\x04\x8aA\xad\x965\x91\u007f\xf6\xcc\xc0\x06Q\xb6\xb9\xf1߃\xbd\xae\xb8\xbcw\v\xc0\xfbW\xb7\xefБ\xeb\"vFR\xb7\fm_8\x8b\x93\xeb\x1a\xa9\x12\x9e\xf7\xa8q \x15\xe3\x847y\x8c\x99 \xa5\xb2\xfd\xbc\x02\xc1\xadU\xf9\xd6\xc0\x96kc\xfb\x1b\xcd\x15\xb8\xc6\xe4\x8aÙ\x1c&\xec\xbe\xf1\nUc/\xe0\xc1\xa7n\xf6\xa0@[\xb1\x1f\xbcj*`\x95j2\x8c\xbb\u007fȾ𪭢\x06\x0e<3n\xdbz\x92˰XE\\\xaa\x05\xda\\\x16opK\xea\xa8P\xd2\xf0\x12u\xac\xf2{\xcerE\aw˸hR\xe5\x9b\xd4sn\x98*?i}Q\x94\xfa\xc5\xcf\xece\r\xf7\xeayH\xa0l\x12\xec\xd9\x01\x81o\x81[@Y\x10_P{\x95\xed\x96\b\xc4p\xa4\xc9\x16\xcb<\x05O\x0fʦ\xca#\xc0ʝl.g\x93b\xfd\xe1?3.\xae\xc16\x92\xbcˏ\xc6/\xdd\xec\xdf\xe4h\xb4J%߄m\x10\xbe\"+\x8f\xf1|0k)Tu2\xa0@7\xb2\xaf\x11\xafp2Ή\xef\xc2.^3p\xe3\x92g0\xf6$\x9f\xcfm\xdf\xdb!\x10W\xf5vh\x81\xd6\xd0]\x92\x9a\xb9\x1f\x00 S\x19\x1dg\xb7\xf7Vj\xce\xf0|6H\x01*\x96>\xe9E\xe63\xf8Ѿwi\xa2\f\x9e\xc4\xee|\xd7%\x8b\xb3\xfd\t\xf9Y\xa2\x1f\xab\xae]a咂\xfa\x80\xabF>I\xf5,W.\xa64\x8b\xd9\xfav\xf1\x8b\x15\xc7o\xa94\x86\xe2\x95/\x02\xd1\xfe^A)d\xb3\xf9\xac\xc0xN\n\x96Ԑoc\x9d\xf8sq\x17s\xeb\xcfL\x0e5Ǐ\xbe\xff4\xb7\xb7\xe9>=\xab\xe7?<\xef\xd1\xeeQ\xc7\xc6֕\xeb\xe1M\xa9ծ4ٹ\xc2m\xb3\x13\xc9O\xf4\xa6|\x13\xdeI\xfbS\xdaW\x96\x8d\x10\xb7$ج\x11ַ\xa2\xea&!DY=@\x1b\xa5\x04\xb2Ӷ\u061c\"\xfaR\xe9|\xd8\x0f֖\xaecC\x98\x8a\x8b$0\xf4\xbc\xf4]\x9f\xfd\xba\xec\xb0\x06\xee\xb2?q\xa7\xff\xf0V\xb1\x8c\xf2\xf6BQ{\xbe\x81n\x8e^c\xb1\xe9S\xac\x93\xc10.tV\xfe\xbe\xc8g\xb1\xfaR\x87s0\xe9/\x0e)\x98\x98r\xd2\x19\xe047E}\xae\xc6\xccxJ\xb9\xd0)\f\x19%\x82\xf8\xa1p'QE\xc0\xc6e\x1d\xc3i\v\x9d\xce\xdc\xc0{ث&\xd1]5C\x9d\x85Z\xfbt\x85=\xe4\x93Ѳ\xc3\xfb\xf5\xf0\x1f\xabB\xbd\xdd%O\x12\xd8=\xef\xdbT\x88s.d\xc9\x0f\xbcl\x98\x18\x1c\xb2\x9eXt\xd2\x03J\x83\xe4\"Uj#\xb1\x8a\xf3\ab\x04_j\x9fr?[\x1d\xcd{tye\xf9\x8b\x8b\xf1\xc3b\xfb\x84\x91:7\xfb\x9c\xdfu\x98_n\x9f\xaf\x8f\x9fSd?-\xa1O\x02].\xad\xe78\xe3\ve\xf4\v\x8a癍S/α\xe7\x94\xc7/*\x8a/\xf6\x16e\x96\u0087E\xeey\x90g\x14\xc0\xb3\x88\xb3\\\xec>\xbb\xc4\x1dJʳxd\x17\xb6\x13%\xebY\xc0\x93\xe5\xec\xb9B\xf5<\xc9\x13E\xec\xfc\xf2\xf4,hW\xba^.J\xbf^\xeb\xd9kD\x01Ӫf\xb1\xb0\xfc\xa2(!\xa3t|N\xc1x\x91b\x17\x16\x87\xdb\xe2\xefĺ疄\x87%\xdf\t\xa09\x85\xe0\x89B\xef\x04\xc4\xd9\xf2onyw\x02\xf6\x82ٝ\x95\x92\x99?\xdb\xc0\xe2o\xac\xae\xb9܍9\x9f+\x1f\xb3\xb21\xaa\x0e\xf7\xd7\x1c\bG\xdf\xff\x1fDN\xa9%\xfd7\x97\x89(+\xe6ո\xb4j\r\x1f\xe4q\x04\xd7\xf5{'\xa3\x8a\xe1G9\xb4\xadg.D\xff\xc3\x13\a\xb6\x0f*|\xc3eұ>\r\x9c\xf2\x99\x93LQz\xe0\xef.\x05U_N\x86\xf73u\xf3\xfes\xcau\xe6v\u007f\xa1\xff\\5\xc2\xf2:y\x88k\xad\x0e\xdc\xe5\xfd\xf6xl\xe9\xf9w\xe5>\xf9\xd8\x1c\x1d\xa4/_\xdb\xf3\xb5>\t\x05X\xeaT<\xa3\x10\xc0\xcc\x18\xfd\xc2\u007f\xf6X\xa8\x95\xfb\x92\x898\x19\xe5!|\x1ey\xeb\xce`*\x06\x97\U00043f0a\xc0\xb8O'M\"\xc71i]\xe6=\\\uf33bw\xbf6\xa8\x8f\xa0\x0e\xae\xd0\x1b\\\x9e\x85\x9ej\xaf)\fEdQw\x05\x05\xe8?\xb6=\xf1\xfc;\x8d\x01\x1f\xa4\xb7\xc1I\xb0'{tpHiu\xd1\x0e\xe9g\nd&\x86&\xa1J\xd5\xceN\xcbì\xa9\xc9mH\xben\xecs~\xf4\xb3\xe8w\\%\x02\xba<\x06\x9a\x01\x99\xdb`\x9cW\x94Xl(\xbeV,\xb4\x14\re\xbb\x81y\r\xc3\xd7h\x14>\xa3A\xf8\x8c\xa8輸(\x9bL9\x8d\xc0W\x89\x8e\xae\x18\x1f]#B\xba,FZ\x00y\xd2\xe0\x9bӺ\x9bUGˮ\xc2\xe4\xd4͖K\xb7\xf3-\xb9\x19\xad\xb8\x19\xf5\x9d\xa5\x9df\xb4ܞ\xd7j\x9bA\xc3+EOW\x8a\x9f\xae\x11A]7\x86Z\x8c\xa2\x16%g\xf6\xef\x8b\xcb\x00\xb1`\xfcY\x95\xf8\xa0\xb4]r\xf8\x1fN\xc7'\x8at\xbd H\x89\x12d\x1c\x9a\xaa\x05\x90/\x1f\xfc\xf8ːJ\xd7\xd3\xc2\xfa\x0fߗ\xf0\xf9\xda\x0e\x9cG\x84\\\xd2\x18\x9f%\xf0\xa0\xf9\x0e\x17#Ym\xf6\x89\xf0\xee\xe5\xc8Ho\xa2\xfd\xdd \x05\x19d\xd3\x14\x05\x1a\xb3mD,d\xbb\xfbް\x8cÓ}\x97\x11\x873*\xb6i\xeflջ\xed\xe8&\x833&\xa1&gTd\xc1j\xdb\xe8 \xe6E\xa3\xb5C\xd9\xff\xa7\xb6\xa3\x1b\x9a\x06`\xa7\x95V\xe84\x1a܉7/!\x1f\xc73\xdc=h\xba\xecU\xd6\xfb\x17ٴ\x05\xf3T~\x8a\x99\xb6٩\\\xf7`{0ν'\xd0X\x02\x1eP\x82\x92\xae\x93\x18˹F\xb8o.\xfe\xd5\a\xd4oM\v\xc7\xd5\xfa\xb7Jãeڶ[\x1fK\xc4V\xe9\x8a\xd9;(\x99\xc5\x15;\xccB\xa6/\x99\xd2z9U\xe9Z\x92\x83?\xeb\xfa\x88\x1d{\x85\b\x8d\xc4\x15\x1a\xc3v\xf1\xe6\xa4g\xd4\b;\x94D\xe2\xb9kt\xba^\xecp\x82ۖ\x10\xa2\x16+l\xc3\xc2\x02\xdeR\xb6I\xdcT\x02\xd0_\xceFC\xd8n\xf2\xdcpiq7J\x9f\x86>\xf0\xaf\xc8\xcc\xe9e~#B\xfc\xdc\x1f\x1b\x82_O\x03\xff\xe18\xf3\xfd\x1b\xee\xee7\xcb5\xcey\bʭ|VWF\xbdgfI]>И\xf6\x03\x89ޡl5\xe5\u05c9=\xa5\x1b\xb6W\xf0\x19\x9f\x13o\u007fvB\xef\x12\x1a飴\x82{\xf9\xa0Վb\x8cğ\xbf0n\xb9\xdc\xfd\xac\xf4\x83hv\\\xb6\xdd1\xe7\r~`\xdar&\xc4\xd1\xef'1\xf7c<̉\xff\x96gO\xfc1Ǥ\x80\xf3b4\xe0\x87u\xc1\x11\x97\xfe\xa0\xbb\xcf\x136\xaa\xb1\xfdS\xf1\xd6t\a&\x9d\x99u\xd0\xd6\xf0YY\x8cI7>\x04\xca\rl\xd0\xd8\x15n\xb7J[\x1f\x8c\xadV\xc0\xb7AQ\xa7\x82\fƅ\xf35\xfcU\x84䀴\x85\xdf\xd6\xf2)\rL\x1eA\xbbS᜔\x8a\x1d}\xf7 +\x8a\x86\xf4\xc0;cYʠ\xbdȵu\xceM\x90扼Ĩ\t\xab\x1d\xdf~\xe8\xd8T\x1bԮ=\x9a\xfe\xf6\xa4s_Nx\x15\x94,8\x80\xfb\xbe\xa2\xf7\xe1\x16\x18:\xce\xe9\xf8xN\xf9\xb8\xff\x95e\xe2~\xdaQ\x1b\xf6\n\xb7\x83#\x02n\xfa\x18\x8d\xc1\x9dk\xd3mB\xdcĩijb\xcf\xe4\x8e\xc4G\xabf\xb7\x8f\"8\xa5\xa9\xa7\xf2!\x8d\xbb\xf2\xadv'\xd5\xc4\xe4\xb5m\xb4\xec\xe5^B:\xbb\xec\xb6;\at\x9e\x843~\xa6\xee\x9a\xe5:\x9d\xf1\xc1\u007f\xf5\x90\x92\x99\x94\xb731y\x82\xfe\x89\xfd\xb3v\n3GY\xccw\xf0\xf9Fm>\xd3W?G\x8c$\xbe\xad\x06\xbc\x04\xdfvr>\xbe\x9d\xd7+\x8e\x9d/u\x0e\xf2\xd3~\xf6+\x90ë\xf4Kh\xe1gN\x1d<\x87_b\xe7g\xb1;d\x1bP\x92\x83骺\xa3\x9c\x06D\xb7\xed\xcf(Fڹ\xd8>\xd0U\xd9j\x9e\xaa\xa0\x16\xa8ִ7\xf6\xbfo\x90@}uQE\xb5\xa4x\x1f!.3\xaa\x86$\xc9L\xf2\x03\x12\xb8X\xadV\x17\xac\xe2\xdfPi.\xc55\xb0\x8a\xe3w\x83\xc2\xfe\xa5\u05cf\xff\xae\xd7\\\xbe;\xbc\xbfx\xe4\"\xbf\x86\x9bZ\x1bY~E-k\x95\xe1G\xdcq\xc1\r\x97\xe2\xa2D\xc3rf\xd8\xf5\x05\x00\x13B\x1af?k\xfb'@&\x85Q\xb2(P\xad\x1eP\xac\x1f\xeb-nk^\xe4\xa8\bx\xe8\xfa\xf0\xe3\xfa\xdf\xd6?^\x00d\n\xa9\xf9=/Q\x1bVV\xd7 ꢸ\x00\x10\xac\xc4k\xd0\xd9\x1e\xf3\xba@\xbd>`\x81J\xae\xb9\xbc\xd0\x15f\xb6\xb7\a%\xeb\xea\x1a\xda\x1f\\#\x8f\x89\x1bŝoO\x9f\n\xae͟{\x9f\u007f\xe6\xda\xd0OUQ+Vt\xfa\xa3\xaf\x9a\x8b\x87\xba`\xaa\xfd~\x01\xa03Y\xe15|\xb6]U,\xc3\xfc\x02\xc0\x0f\x8c\xba^\x01\xcbs\"\x15+n\x15\x17\x06Ս,\xea2\x90h\x059\xeaL\xf1\xca\x10)\xee\f3\xb5\x06\xb9\x03\xb3\xc7n?\xb6\xfc\xa2\xa5\xb8ef\u007f\rkM\xf5\xd6՞\xe9\xf0\xab#\x91\x03\xe0?\x99\xa3\xc5M\x1b\xc5\xc5\xc3Xo\x1f\xe0FI\x01\xf8\xbdR\xa8-ʐ\x13g\xc5\x03<\xedQ\x80\x91\xa0jA\xa8\xfc\a\xcb\x1e\xebj\x04\x91\n\xb3\xf5\x00O\x8fI\xff\xe3\x1c.\xf7{\x84\x82i\x03\x86\x97\b\xccw\bOL\x13\x0e;\xa9\xc0칞\xa7\x89\x05\xd2\xc3֡\xf3\xf3\xf0\xb3C(g\x06=:\x1dPA\xaa\xd7'\x12ك\xf9\xe1\x01\x13\x80\x11\x89*Vk\x12\x8e\xb6\xf5m\xf7\x93\x03\xb0\x95\xb2@&.\xdaJ\x87\xf7N\xf6\xb2=\x96\xec\xdaW\x96\x15\x8a\x0f\xb7\x9bo\xffz\xd7\xfb\f\x03Y\xf2\x94\x02\xae\x81\xc17\x9a\x18\xa0\xfc\x14\x06\xb3g\x06\x14ZΣ0\xb6F\xa5p\x15\xa8\x9b7 \x01\xa4\x82\n\x15\x979\xcf\x02W\xa8\xb1\xde˺\xc8a\x8b\x96A\xeb\xa6A\xa5d\x85\xca\xf00\xf5\\騚\xce\xd7\x01\xc6?\xd8A\xb9ZN\x12Q\x93\xf0\xf9\t\x85\xb9\xa7\x83\x9b\x1f\\\xb7\xf8\x13\x93z\x80\xc1Vb\x02\xe4\xf6\x17\xcc\xcc\x1a\xeePY0\x01\xebL\x8a\x03*K\x81L>\b\xfe\xff\rlm\xa5ސ0\x1a\xf4\xfa\xa0-4\x81\x05+\xe0\xc0\x8a\x1a\xaf\x80\x89\x1cJv\x04\x85\xb6\x17\xa8E\a\x1eU\xd1k\xf8o\xa9\x10\xb8\xd8\xc9k\xd8\x1bS\xe9\xebw\xef\x1e\xb8\t*6\x93eY\vn\x8e\xefH[\xf2mm\xa4\xd2\xefr<`\xf1N\xf3\x87\x15Sٞ\x1b\xccL\xad\xf0\x1d\xab\xf8\x8aP\x17\xa4f\xd7e\xfeO\x81\xa3\xfa\x87\x1e\xae'\xf3\xcd\x15R\x84\x13\x1c\xb0\x1a\xd1\t\x8ck\xeaF\xd1\x12\xda~\xb2\xd4\xf9\xfa\xe9\xee\xbe+L\\\x0f\xa9Ot\xefHX\xcb\x02K0.v\xe8g\xf4Nɒ`\xa2\xc8+Ʌ\xa1?\xb2\x82\xa3\x18\x92_\xd7ے\x1b\xcb\xf7\xbf֨\x8d\xe5\xd5\x1an\xc8\xeeX9\xac+;\x03\xf35l\x04ܰ\x12\x8b\x1b\xa6\xf1\xd5\x19`)\xadW\x96\xb0i,\xe8\x9a\xccaeG\xb5\xce\x0f\xc1\xbcE\xf8\x15\xe6\xf8]\x85Yo\xca\xd8v|\xc73\x9a\x18\xa4=\x1b\x150Р\xae\x8c\xcfZ\xfa\x85\xd4\xd4\xf0\xeb\x00\x0f\xa7\xcbB\xaf\xa8\xad\xfd0{\xe2pkƬ\\9hV\xa7\b9\xe4\xee\x98\x16\xecP\xc2C\x99\xc1\xa4\xaf\xf5R\xed\xdb\tL\xf0\xaan\x1d\xc1\xf1\x84\xab\xf4\x13\x96\x95U\x1b3(\xde\xfbj\x16EK\x9f\xbcq\xa7\x82\xe1\x0fjVz\xed\n'ʍ\xbaۣ\xe5ہ\xe7^{\x9dp\x15&9kK\xa6\xf9\x9d`\x95\xdeKcm\x9c\xac\xcdX\xad\xc1\x00n\xee6\x83F\x1d\xce[\xacȆ\x13\xa3\x8d\x84'\xc6O9튕˛\xbb\r|\xb3.\x11\x06\x98\xe0,9\x98Z\tR\xc7_\x91\xe5\xc7{\xf9\x17\x8d\x90פ\x95\x82]\xbe\x8a\x00\xde\xe2\xceNz\x85\x16\x86m\x80J\xd99\xa0\t5Y\x9b59\x1c9\xeeX]\x18\xaf丆\xf7?B\xc9Em\xf0\x94\xef0\xcd{G$\x02\xe7F\xa3\xef\xe5O\xda12\x81\xa4\x1f#MG\xa6T%s8P\xbd\x18Uy\x81\xa0\x8f\xda`\t[\x0f\xa5\xb1\xd5\xc4\x15\xd2\aE\xe1\xc1h\xd8\x1e\x03\xee\xe3\xe3\xb6^8\xdb\x16x\rF\xd5\xe3\xddNM\xdd1\xda|Emx\x96@\x99\xcb!i\\\xcb\x11\xc2(\xfa!B\x94\x01\x05\xac\x91g\x8f\xd6\xd1\xf4\x14\xb2\xdeBQt\x88;O\x15\x80\xff\x15\xf0\xd1\x1a\xb8̚\x9dko\xce8\x16dB\x85\x84B\x8a\aT\xaeG\xeb*<\xf1\xa2\xa0)\x8d\xa5<\xf4\x9c\xacn\xb1\xb6Eaa\x8d$\xecjkv\xd6`e?*#\\h\x83,__\xbe\x16\xf3\xf0{V\xd49\xe67E\xad\r\xaa;\x1b\xf4\x84`pT\xad\fx\xf8i\xaa\xbdw7\n\x9e\xa1\xe5B\xe6\xea\xc4\xd8h\x9bv\x1c\x8fc\x85.γ\x1c\xf5h\xb6\x1e\x85\xe3\xed\x1a6;\xd0\x18SBF\xc2\xe5\x9f.\xaf\x88\xfd\xbe\xf3\xb1n40\x85\r%\xc6%\x82\x1b,#\xf4\x98U\x1e\v\x18Ŕb\xc7\t6\xb5\xd1\xe89L\x1ai=`\x91\b5~\x1d&5\xdd\xffQ\xd8t\x16w4-\xaf0.,k\n\xaeM\x8f3Cw\xbc\xc1\xccFn\x96B\xd6e\xe6\xc2\xc1\xb4\x8a\xa6É\xdf2\xcd\xce\x11\xe8\x98\x187r\xe3es\xcfb\xd2\xf7;$\xd8^\xca\xc7\x14\"\xfd\x97\xad׆i\x90\xd1J\x1flq\xcf\x0e\\*=\x8c\xf5\xf1;f\xb5\x89\xda.f \xe7\xbb\x1d*\v\x8b\x96\xa7\x9aլ)bM;\xa9\xb6\xa8iƟ\x8c\xabe\xbae\x1eQ#6\x14\n\x06\xa2P\x81\x10\xb7>$Yڜ\x1fx^\xb3\x82\x8c.\x13\x99\x1b\x1fk\xf0\x8b\xb9\n3\x02q\x82\xbf3\xeda\x14\x96K\xbd\x18O\n\xb4AT)UL\t\xbbr\n&N\x86-\xa3\xd0,\x16\x10\xb5E\xd5\x05j\x8f\x8as&[\xbds\xd5r\xca-\x8f\x14l\x8b\x05h,03R\xc5ɓ\"\x04\xae\xa4\xea\xcf\beG4i?z\x99U\xa2m\xb1\xe1͞g{\xe7\xfaY)#X\x90KԤ1XU\x15ǩAC\x8ad\xf8\xce\xe6\x94F[\x12\xd4\xc7\x10nL\x91\xb4%Q\a\xb7eF\x1b\xf7\xa9ވ\xcd\x1b\xd1{h\x8ag\t\xfb\xe6\xa4\xf9\xcb\v\xbb%7GM\x1e\x1c\x96\x959^\x017\xe1k\nԞS\xa7\xff`\x8c;o\xb6l\x86\xad_|\xb6\xbc\b\xd7\x1a4\xfe L#cu\xe7m\xd5\"\x86\xfd\xdcmy\x05|\xd70,\xbf\x82\x1d/\f\x92/5\x87h\xc7љ\xe5\xdcK\x12(\xd5\xf6\xdaR2\x93\xed?5\x8b\xaa\t-\x06\xb4\x1a\x02p~y\x88a\x88\a\t \xa1q*h?\x80+,\xdd>\xc3=͏\xf6\vy\x80\x1f>\u007f\x8c\x85\x83\xfd\x92(\xa9'\x83\xfa0\xf0t\xba(\xd0\x00\x93@v\x06EnZ\x13\xe3\xb9ݤ+`\xf0\x88G\xe7Y\x8d.Ռ\x15\xcbZրTH[[\xa4F\x1e\xf1H\xa0\xfc^U\x12\xbc%\xa2\xe2\xca#\x1eS\xab\x0e\x88j\xf1\xf3\xab䎺\xf6\x03\x8d\"e*\xb5\xa5!\xaa\x9f;`d\xda`a\x99R\n%P\xfc\xcca7\f\xebm\xd0>\xe2\xf1\a\xed\xd8gg͞W\v(`\x156h\xa4\x19\x16v&\xbf\xb1\x82\xe7Mg4O\x16@܈+\xf8,\x8d\xfd\xe7\xd3w\xae-\x8a\"\x87\x8f\x12\xf5gi\xe8˫\x92\xd8\r\xe2L\x02\xbb\xc64-\x853\v\x96.\x8b\xfaoq \x13jE\xb4a\x1bװ\x116>s\xf4Y¦=\x06\xe4\x1cZe\xadioSH\xb1\"3\x1dz[\x00\xb4\x8b\x97g\x95T=N]-\x848\x8a\xa2G\xef\xdeZ+\xf7\xcbɮ\xf0TQX\x15,\xc3<\xec\xf1\xd0\x1643\xf8\xc03(Q= T\xd6n\xa4\v\xd5\x02M\xee\xca\x19R\x98\xeeZ\x84\xe2\xcd\xc2Ȏ\xeaXY\xd9Y\x9fX3\xb09\xa9zd\xbfy\xbaz\xda(ɼ\x93?\x94D\xfdn\x82\xd42˲\x90_\xa7>\x88Cҹ\x1f%\xa3M\xa0\xbfY\xf3J\xe2\xfd\xf74kȸ\xd2k\xf8@\xe9a\x05vۇU\xc2NWI -&\\\x83\x95\x93\x03+\xac\xfb`\x95\xb7\x00,\x9c3!w'\x1eT\x9a\x8ay\xdaK\xedl~\xb3Iu\xf9\x88\xc7˫\x13\xedu\xb9\x11\x97i0\xad\xce?QZ\x8d\xd7\"Eq\x84K\xfa\xed\x92\x1c\xb3%S\xe4\f\xe7m\x81T'W\xa5D\xac%\xa1\x80\x8d\xb5\x83\xd7b\x1b7\xe9Jօ\x9f\x1bE\xb2LWRG\xf6\xea#h\xddJm\xdc\x02`\xcf\xdd\x1eY!L\x89\xfe\xfc\xaa!\xb0\x1d\xed\x97\x19\xa9Bj\x90U\xbb\x83\x05r\xcby=\xcf{\xb7s\xe3W#\x1d`\x1bd^\xb6\x1a\xc2\xe9\xf4K\xb7yd\xff?\x0f3#g\x89`WJf\xa8\xf5\xbc(%Z\x8e\x99\x05\xdbf\xb1\x96\xb9\xe0m\x97\xa4\x9aS\x96\x92CY\xe6\x8a[Ҟ\x11\xd8|\xfa\xdeYw\xb6j\xc8\xfe\x9d\"\xca\xe7\xe0\b\x946\\\x96l\x98\xa6\x96\x8c\xee\x8dk\x1d&\xa0\a\xe6\x02&\xf5P\x93RY\xe67{\x91\xfc\xad9\x1e%\x17\x1b\xea\b\u07bf\x9a\xb3\x02A\x95㹡\xccMh\xdf2\xa4\xf9\x90\x1a\xbfBHv\x92\xb4W\xa3\xb0\xc7\xd9ӝ\x8ctN\x81u\xa6\x854\xdd\xc5\x1a\xdf\xd3\x0f\x1av\\i\xd3\"\xbc\x00*ה\xf4\xf1\xba1\xa6\xf8\xa4\xd4\xd9!\xe6\x17\u05fa\xb3\xac\xb8\x97O>EpI`\x1d\x88\xbfg\a\x04\xbe\x03n\x00E&kA\v^V]\xd8n\x16@tLt\xc6$\xd1fv\x1a\x8b\xbaL'Ȋ\xa4\x93\x8b\xd9ձn\x93\x9f\x18O[\x9d\x82\xf3\xd8j\xa6\xd2\xf0\xc6J?\xb7\xd0\xe7\xe3usAK\xf6\x9d\x97u\t\xac\xb4lY\x127\xee\\&_H\x1cu\xbc~b\xdc\xf8||\xb7\xb1\xbaL\x9bf\xb2\xac\n4\x18r\xf42)4ϱq\x1f<\xffG3\x1ec\x85\xc1\x8e\xf1\xa2V\vt\xf4b\xce,\x8dۼzz\xf9`,\x1d\x91\x15\x113q\xd1}\x81\xd3&5m\xeaJk\xf4\x9a\x94i;%\xc3dr\xa7\x12\x13\xbc\xf0\x178\xbb\x12\x108\xf7\xec\xcaf\xaa\xfd˝]\xf1h\x0e\x17\xceݡ\b01\xa3\x97~r%Сw\xf2-\x02\xb59\x0f\xe7\x13\xc3\\\x1aR\x89,l\xe9\xb8\x1c\x92<\xd2ḱ\xed\xa11Z\xe7WN\x9a?I\xb6\\t\xde\xe0$\xd7\xf2u\x0e\xd0D$e\x01W/\xfft\xf9\xfb \xffYT\x8f\x12\xdb\xfd/6\xba\x96\xb0NѺ\x83\xe9\xdd\xf4\xc8~\x9a\xea\xefG\x9aϑ\xe1\xd4331\xbd\x14Wg\x1db\xaa\xde\x19\x8d\xdf6-\r\x96_*o\xb9\xd2OJoF\x9a=\xe3\xac4\xd3G\x91\xed\x95\x14\xb2\xd6~E\xc7\xf6\xf0!s\x87\xc7CG\xfa\xf4ps\x8cM\x1a\xde\xc3^֑s\x193tMȖ\x8d\xe7\xc8\xfa\xac\v4\xec\xf0~\xdd\xff\xc5H\x9f1\x1b\xc1\xfa\x89\x9b\xbd;\xc1\xcf\xf2\xdc:\xe6\x9dc9a\xf2\xfa[<\x86\x82\x17\x81(\x15\b^8\xa9\f\x10\xfaF\xf3K\xe5\x96\xf8\xce\xf6S\xe6\x17\x9a\xd2\xf3j\x97f\xd36\xf9\x8f\xf3^\xf13rh\x97\x1dp\x9a͗MA\x1aR\xb2d\xc7\xf3_g\xa0.ɍM]CLȃM\xcf~M#\x0f\xd0\xdd;\xa99\xaf\xc9Qgj~\xeb\xebd\xb5&\xe6\xb2v2TgA\x9e\x99\xc1\x9aL\xb0\xb4l\xd5\xe4\x1c\xd5N\xe6\xe9<\xb5&2S\xc7\xf3MgA\x8e壦d\x99&᚜[\xdad\x8c\xce\xef\x84<+\xa3\xf4\xe5Ϯ\xbc\xe4:\xc5t~hRVh\xd2Z\xc6<\xceIy\x9fK\xb3=\x93\xa8\xba4\xb3\xb3\xc9ڜ\xe88)\x9f\xf34Wsj(\xb3Y\x9c\xf1\f\xcd)\xb0c\xb9\x9b\ty\x99\x13 \xbb\x19\x9b\x8b݀Yi\x9a\xa90~?V(\xf3\xb6\xb6\xf85$\U000390d6\xaa\xe7\x02\xa7\x84j_\x06M,\xef\x83\xd77\xe6V\xc7\x03_\xe7l\x9f\xe1VG@nvPօ\xe1Uѹ\xa0\xca\xec\xf1\xd8\\\x80\U000cb923\xe3\xdb#A\xfb\xf2\xb5\x11\xe0\x18\xc8~\x80\xc04\xb7\xb2\xe0i[\x95_\xbb-\xf8\xc8\r9t\v\x9d\xb5T3\xf4\xab\x02\x00\xf2\x0f\xfb7\xe6\xeedQȧ3W\"X\xc5\xff\x93\x9e\xa5H[\xb8\xfap\xbb\xa1\xeaA\xb0\xe8I\x8b&\x95\xad\x11\xb3-N\xeb\xe7v\xe0\xe4It\xa1\x8e\xa4\x926\u007fN@\xa4K\xe1\x83\xdb\xe0\xb5r&\xadR\xba\xdd8,\xd7$[L\x1cA\xfak\xbf\xb9\xcaW\x15S\xd1\x1d7\xf0\"\xa1\xafz\x18\x06\xb3<\xb7\xbc4i\xa5N/\xb9\xef\x96\x1e\xcd\xc3}\xf7\xb4\x13{\xac\xfa{\xdcD\xe9\x0e=\x9f\x83\xd3\xf4)\xe2\xd9\xf3ï\x80Ӵ\a\xb4\"*F~\x8a\xe6\xc6\xcdLr\xedo\xf8\xf6W\x18'L\xf2\xbb~\x8b\xb1\x1b\xe6\xfdM\xce\x01\xf6\x84.\xb7\xf2y\xfb\x8dB\xa5F7xq\xf6\x81PX\xe6\x1a\\\xf4\x19\x01\x19\xbb\"\x1e^&sM\x1b\xa9\xd8\x03\xfe,\xdd-\xfe)\xd4\xea\xb7\xe8=\xe4\xe0\x1d\x91\x90\xc7\xea\x05+\xa6\xb9\xfc؆\x00\xdb\xf4\xf6\x93\x8b\xc5-\xb6\xb1y;#\x8b\xc6\x14\t\x83\xbb\xbf\xff\xd9\r\xc8\xf0\x12\xd7\x1fk\x97\xeb`\x95\x8cFK\xe90P\xd7h\x1b\x9f\x8a{\xf9D7sw\xaf\xda\xef\x90.Eؿ\x8d\xb7\xec\xf8\f\x1d&N%3\xc9]\x14\x16\xd3Zf\x9c\xdc\fZ\xef\xa5,\xf6\u05fb\xc7v\xca]\x9cP\x16\xb5\xc6/O\x02\xd5\xd70Q\xf5F\xc4\xee\xd2\xef\x91\xf0/'\r\xa3\xf7\xe8\x1bI\xce͠\xfa\x98S+<\x81\xb4{w ,\\sݼ6qJ\xba\x99\xf9\x1f\x9f\xfb\xe3jy5\xfe\xc0êys\xe2\"\x81\xb2\xee]\x85\x94\xe7D\xdc\x03\f\x19\xabL\xad\xbc?\x95Պ.\xf5\xb5@\xd0\xddy{ރ\"\xed\x03M3\xbcl\x9flj\x97\xf2f\x1f\x88\x1a\xe1_\xf3$H\xf4\x8d\f\xe78\xbb\a\x9cV\x16\xfey\xec\x1c\x9d\at\t\xf2\xdc\xf3)\xb6Ns\x02\xc9\x13\x9a\x1a\x86˓\xefb\xa8\x8f\x1f)Y\xc1g<\xf5ZW\xf0I\xd8A\x9c\x9auwn\x04sZ\x00\x1c{Lir\x88\x87\xa6\x15\x1d\xda\x19\xd1\x16}57\xa8>H1\xa4\x87)\x9a*\xee\x80\xce\x18[\xff\x99\xef\xdc\xealf\xc7\xf4/'5\xa2\x8akRi\xc5\x14\xd6\xe8\x94:\xf9\xa8Q\x1d\xe8%\x88 $ކw\xbf\xd4\xdb\xf6.k\xf8\xdb\xdf/\xdaYɲ\f+\xe3SY\x1d\xe6\xee\xe1\xbaK\xf7\xb2Cx\x97\x8e\xfe̤pQ\xb4\xbe\x86\xff\xf9\xbf\v\xf0\x06\xf8[x|\xce~\xfcG\x00\x00\x00\xff\xff\xd8\xf1\x03\x9c\xe6o\x00\x00"), + []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec=Ms\xdc:rw\xfd\x8a\xae\xc9\xc1ɖf\xfc\\9$\xa5\x9b\"\xfb%S\xeb\xd8*K\xebK\x92\x03\x86\xec\xd1\xe0\x89\x04\xb8\x008\xf2dk\xff\xfb\x16\x1a\xe07A\x82#\xa9\xdeG\t\x17[\x1c\xa0\xd1\xe8n\xf4\a\xd0\x00.\xd6\xeb\xf5\x05+\xf8wT\x9aKq\x05\xac\xe0\xf8à\xb0\u007f\xe9\xcd\xe3\xbf\xeb\r\x97\xef\x8f\x1f.\x1e\xb9H\xaf\xe0\xa6\xd4F\xe6\xdfP\xcbR%\xf8\x11\xf7\\på\xb8\xc8Ѱ\x94\x19vu\x01\xc0\x84\x90\x86\xd9\xcf\xda\xfe\t\x90Ha\x94\xcc2T\xeb\a\x14\x9b\xc7r\x87\xbb\x92g)*\x02^u}\xfci\xf3o\x9b\x9f.\x00\x12\x85\xd4\xfc\x9e\xe7\xa8\rˋ+\x10e\x96]\x00\b\x96\xe3\x15\xe8\xe4\x80i\x99\xa1\xde\x1c1C%7\\^\xe8\x02\x13\xdbۃ\x92eq\x05\xcd\x0f\xae\x91\xc7č\xe2η\xa7O\x19\xd7\xe6ϝϟ\xb96\xf4S\x91\x95\x8ae\xad\xfe\xe8\xab\xe6\xe2\xa1̘j\xbe_\x00\xe8D\x16x\x05_lW\x05K0\xbd\x00\xf0\x03\xa3\xae\xd7\xc0ҔHŲ[ŅAu#\xb32\xafH\xb4\x86\x14u\xa2xa\x88\x14w\x86\x99R\x83܃9`\xbb\x1f[~\xd1R\xdc2s\xb8\x82\x8d\xa6z\x9b\xe2\xc0t\xf5\xab#\x91\x03\xe0?\x99\x93\xc5M\x1b\xc5\xc5\xc3Xo\xd7p\xa3\xa4\x00\xfcQ(\xd4\x16eH\x89\xb3\xe2\x01\x9e\x0e(\xc0HP\xa5 T\xfe\x83%\x8fe1\x82H\x81ɦ\x87\xa7Ǥ\xfbq\x0e\x97\xfb\x03Bƴ\x01\xc3s\x04\xe6;\x84'\xa6\t\x87\xbdT`\x0e\\\xcf\xd3\xc4\x02\xe9`\xeb\xd0\xf9\xdc\xff\xec\x10J\x99A\x8fN\vT%՛\x81Dv`^?`\x040\"Q\xc1JM\xc2Ѵ\xbem\u007fr\x00vRf\xc8\xc4ES\xe9\xf8\xc1\xc9^r\xc0\x9c]\xf9ʲ@q}\xbb\xfd\xfe\xafw\x9d\xcfГ%O)\xe0\x1a\x18|\xa7\x89\x01\xcaOa0\af@\xa1\xe5<\nck\x14\n\xd7\x15u\xd3\x1a$\x80TP\xa0\xe22\xe5I\xc5\x15j\xac\x0f\xb2\xccRءeЦnP(Y\xa02\xbc\x9az\xae\xb4TM\xebk\x0f\xe3wvP\xae\x96\x93D\xd4$|~Ba\xea\xe9\xe0\xe6\a\xd7\r\xfeĤ\x0e`\xb0\x95\x98\x00\xb9\xfb\x05\x13\xb3\x81;T\x16L\x85u\"\xc5\x11\x95\xa5@\"\x1f\x04\xff\xff\x1a\xb6\xb6RoH\x18\rz}\xd0\x14\x9a\xc0\x82epdY\x89\x97\xc0D\n9;\x81B\xdb\v\x94\xa2\x05\x8f\xaa\xe8\r\xfc\xb7T\b\\\xec\xe5\x15\x1c\x8c)\xf4\xd5\xfb\xf7\x0f\xdcT*6\x91y^\nnN\xefI[\xf2]i\xa4\xd2\xefSHcm\x9c,\xcdX\xad\xde\x00n\uedbdF-\xce[\xacȆ\x13\xa3\x8d\x84'Ƈ\x9cv\xc5\xca\xe5\xcd\xdd\x16\xbe[\x97\b+\x98\xe0,9\x98R\tR\xc7ߐ\xa5\xa7{\xf9\x17\x8d\x90\x96\xa4\x95*\xbb|\x19\x00\xbcý\x9d\xf4\n-\f\xdb\x00\x95\xb2s@\x13j\xb24\x1br8Rܳ23^\xc9q\r\x1f~\x82\x9c\x8b\xd2\xe0\x90\xef0\xcd{G$\x02\xe7F\xa3\xef\xe5\xcf\xda12\x82\xa4\x1f\x03MG\xa6T!S8R\xbd\x10Uy\x86\xa0O\xda`\x0e;\x0f\xa5\xb6\xd5\xc4\x15\xd2\aY\xe6\xc1h\u061d*\xdc\xc7\xc7m\xbdp\xb6\xcb\xf0\n\x8c*ǻ\x9d\x9a\xbac\xb4\xf9\x86\xda\xf0$\x822\xab>i\\\xcb\x11\xc2(\xfa!@\x94\x1e\x05\xac\x91g\x8f\xd6\xd1\xf4\x14\xb2\xdeB\x96\xb5\x88;O\x15\x80\xff\x15\xf0\xd1\x1a\xb8Ě\x9d+o\xce8fdB\x85\x84L\x8a\aT\xaeG\xeb*<\xf1,\xa3)\x8d\xb9\x00\xe7\x97W1\f\xf1 \x02$\xd4N\x05\xed\ap\x85\xb9\xdbg\xb8\xa7\xf9\xd1|!\x0f\xf0\xfa\xcb\xc7P8\xd8-\x91\x92:\x18\xd4u\xcf\xd3i\xa3@\x03\x8c\x02\xd9\x1a\x14\xb9iu\x8c\xe7v\x93.\x81\xc1#\x9e\x9cg5\xbaT3V,kY\rR!mm\x91\x1ay\xc4\x13\x81\xf2{UQ\U0001620a+\x8fx\x8a\xad\xda#\xaa\xc5ϯ\x92;\xea\xda\x0f4\x8a\x98\xa9Ԕ\x9a\xa8~\ue011q\x83\x85eJ\xa9*\x15\xc5\xcf\x1cvͰ\xce\x06\xed#\x9e\xdei\xc7>;k\x0e\xbcX@\x01\xab\xb0A#Ͱjg\xf2;\xcbxZwF\xf3d\x01ĭ\xb8\x84/\xd2\xd8\u007f>\xfd\xe0ڢ(R\xf8(Q\u007f\x91\x86\xbe\xbc*\x89\xdd \xce$\xb0kL\xd3R8\xb3`鲨\xff\x06\a2\xa1VDk\xb6q\r[a\xe33G\x9f%l:`\x85\x9cC+/5\xedm\n)\xd6d\xa6\xab\xde\x16\x00m\xe3\xe5Y%U\x87S\x97\v!\x8e\xa2\xe8ѻ\xb7\xd6\xca\xfd2\xd8\x15\x9e*\n\x8b\x8c%\x98V{<\xb4\x05\xcd\f>\xf0\x04rT\x0f\b\x85\xb5\x1b\xf1B\xb5@\x93\xbbr\x86\x14ƻ\x16U\xf1fadGu\xac\xac\xed\xac\x8f\xacY\xb19\xaaz`\xbfy\xbaz\xdc(ɼ\x93?\x14E\xfdv\x82\xd42˲\x90_C\x1f\xc4!\xe9\u070f\x9c\xd1&\xd0߬y%\xf1\xfe{\x9c5d\\\xe9\r\\SzX\x86\xed\xf6\xd5*a\xab\xab(\x90\x16\x13\xae\xc1\xcaɑe\xd6}\xb0\xca[\x00fΙ\x90\xfb\x81\a\x15\xa7b\x9e\x0eR;\x9b_oR\xad\x1e\xf1\xb4\xba\x1ch\xaf\xd5V\xac\xe2`Z\x9d?PZ\xb5\xd7\"Ev\x82\x15\xfd\xb6\"\xc7l\xc9\x149\xc3y[ \xd5\xd1U)\x11kI(`c\xed\xcak\xb1\x8d\xebt%\xeb\xc2ύ\"Z\xa6\v\xa9\x03{\xf5\x01\xb4n\xa56n\x01\xb0\xe3n\x8f\xac\x10\xc6D\u007f~\xd5\x10؞\xf6ˌTUj\x90U\xbb\xbd\x05r\xcby=\xcf{\xb7s\xe3W#\x1d`\x1bd\xae\x1a\r\xe1t\xfa\xcam\x1e\xd9\xff\xcf\xc3L\xc8Y\"\u0605\x92\tj=/J\x91\x96cf\xc1\xb6^\xace.x\xdbG\xa9春\xe4\xaa,s\xc5-i\xcf\bl>\xfdh\xad;[5d\xff\x8e\x11\xe5sp\x04J\x1b\xces\xd6OS\x8bF\xf7Ƶ\xae&\xa0\a\xe6\x02&\xf5P\x92RY\xe67{\x91\xfc\xad9\x1e9\x17[\xea\b>\xbc\x9a\xb3\x02\x95*\xc7sC\x99\x9b\xaa}Ð\xfaCl\xfc\nU\xb2\x93\xa4\xbd\x1a\x85\x1d\xce\x0ew2\xe29\x05֙\x16Ҵ\x17k|O\xef4\xec\xb9ҦAx\x01T\xae)\xe9\xe3ucL\xf1I\xa9\xb3C̯\xaeukY\xf1 \x9f|\x8a\xe0\x92\xc0\xba\"\xfe\x81\x1d\x11\xf8\x1e\xb8\x01\x14\x89,\x05-xYua\xbbY\x00\xd11\xd1\x19\x93H\x9b\xd9j,\xca<\x9e k\x92N.fW\xc7\xdaM~fw\xd0Ru\\\xe0\x98P\xedk\xaf\x89\xe5}\xe5\xf5\x8d\xb9\xd5\xe1\xc0\xd79\xdbg\xb8\xd5\x01\x90\xdb=\xe4efx\x91\xb5.\xa82\a<\xd5\x17\xe0\xfc\"\xe9\xe8\xf8\xeeDо~\xab\x058\x04\xb2\x1b 0\rO\x98e\xf6\xdf\x01\x15\x12w\x1d\\\"\xd7hmNx\x1b\xcf_\xfc\xe3\uf4bbt\v[t\xae\x9e\xecYn!U\xf7\x05\x9d\x11\x93N;\xbb\xceG\xa7o\u007f-Q\x9d@\x1eQ\xd5^MP̚\xf3\x96~jj\x1b\xe1U\xaa\xc4\xeb$w)aW\xb5\x84gC=\xa1\xe1Z83\xdbǕ`Y\x1d\xd2\x04GS\xaa\xd3\xc6B!\x10B\xd6\x10\x02\xedc|\xe9%\a\x10_#Tz\x89`)ʭx\x8d\x80\xe9\xb5B\xa6\xa5AӒԋ\xa8\x03\x84\xaf\x11:-\t\x9e\x16y\x80\xf1\a\x04_\xeb`\xe0+\x04Qg\x87Q\x8bH\x17{\xf0oq0\x151\xbe\x99\x83~\x03\x8f+\x02d\xf0\x80\xdfx@\x15\x01qp\xb0o6\xa4\x8a\x99\a\xfd\xa0\xeb\xd9\xc7\xf4\xa2Ӑ\x16\xed\x85Ǧ\x10\xc5mS\xcf\x1f\xbf\x8b\x83Wɉ\xb4\x1a\xe9v\xeb\xb0ܐ`1q\x02\xe9\xef\xfc\xe6*]\x17L\x05\xb7\xdb\xc0˃\xbe\xec`X\xd9乵\xa5I\x135\xbc\xe1\xbe]:4\xaf.\xbb\xa7m\xd8S\xd1\xdd\xe0&J\xb7\xe8\xf9\x1c\x9c\xa6\x8f\x10\xcf\x1e\x1e~\x05\x9c\xa6ݟ5Q1\xf0S01nf\x86k\u007f\xbd\xb7\xbf\xbf8b\x8a\xdfu[\x8c]/\xef\xafq\xae`O(r+\x9f\xb7\xdf)N\xaau\x83\x17g\x1f\x05Uk\\\xbd[>\x03 C\xf7\xc3\xc3ˤ\xadi#\x15{\xc0\xcf\xd2]\xe1\x1fC\xadn\x8b\xce+\x0e\xde\v\xa9\x92X\xbd`\x854\x97\x1f[\x1f`\x93\xdb>\xb8U\xdcb\x1b\x9a\xb73\xb2hL\x161\xb8\xfb\xfb\xcfn@\x86\xe7\xb8\xf9X\xbaD\a\xabd4ZJW\x03u\x8dv\xe1\xa9x\x90Ot-w\xfb\x9e\xfd\xd6K&H\xb9\xf4\x94\xadx\xd6h\x8e\x9d\x9b\xec+\xd2\xc5\b\xfb\xf7\xf1\x96-\x87\xa1\xc5ĩL&\xb9\x0f\xc2bZ˄\x93\x8fA\x8b\xbd\x94\xc2\xfez\x97\xd8N\xf9\x8a\x13ʢ\xd4\xf8\xf5I\xa0\xfaVMT\xbd\x15\xa1\x8b\xf4;$\xfcˠa\xf0\x12}#ɳ\xe9U\x1f\xf3h\x85'\x90v\x8f\x0eT\xab\xd6\\\xd7OM\fI73\xff\xc3s\u007f\\-\xaf\xc7_wX\xd7\x0fN\\DP\xd6=\xaa\x10\xf3\x96\x88{}!a\x85)\x95\xf7\xa7\x92Rэ\xbe\x16\b\xba\vo\xcf{M\xa4y\x9di\x86\x97\xcd{M\xcd:\xde\xec\xebP#\xfc\xab\xdf\x03\t>\x90\xe1\xbcf\xf7z\xd3\xda\xc2?\x8f\x9d\xa3\xf3\x80n@\x9e{;\xc5֩\x8f\x1fyBS\xc3\xea\xe6\xe4\xbb\x10\xea\xe3\xe7I\xd6\xf0\x05\x87^\xeb\x1a>\t;\x88\xa1Yw\x87F0\xa5տ\xb1\x97\x94&\x87x\xac[щ\x9d\x11m\xd1Us\xbd\xea\xbd\xfcBz\x95\xa2\xae\xe2N猱\xf5\x9f\xf9\xde-\xcd&vL\xff2\xa8\x11T\\\x93J+\xa4\xb0F\xa7\xd4\xe0\xa3Fu\xa4g *!\xf16\xbc\xfd\xa5\xdc5\x17Y\xc3\xdf\xfe~\xd1\xccJ\x96$X\x18\x9f\xc7\xea0w\xaf֭ܳ\x0eգt\xf4g\"\x85\v\xa1\xf5\x15\xfc\xcf\xff]\x807\xc0߫\x97\xe7\xec\xc7\u007f\x04\x00\x00\xff\xff\x87\x91\x8e\xf4\xe3o\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4VO\x8f\xeb4\x10\xbf\xe7S\x8c\x1e\x87w!\xe9{\xe2\x00\xca\r\x15\x0e+`\xb5\xda>\xed\x05qp\x9di;\xacc\x9b\xf1\xb8K\xf9\xf4\xc8v\xb2m\x93\x94]\x90\xf0-\xf6\xfc\xf9\xcdo\xfed\xaa\xba\xae+\xe5\xe9\t9\x90\xb3-(O\xf8\xa7\xa0M_\xa1y\xfe.4\xe4V\xc7\xcf\xd53ٮ\x85u\f\xe2\xfaG\f.\xb2\xc6\x1fpG\x96\x84\x9c\xadz\x14\xd5)Qm\x05\xa0\xacu\xa2\xd2uH\x9f\x00\xdaYag\fr\xbdG\xdb<\xc7-n#\x99\x0e9\x1b\x1f]\x1f?5\xdf6\x9f*\x00͘տP\x8fAT\xef[\xb0ј\n\xc0\xaa\x1e[\b\xc8II\x94\xc4\xc0\xf8G\xc4 \xa19\xa2Av\r\xb9*x\xd4\xc9\xf1\x9e]\xf4-\x9c\x1f\x8a\xfe\x00\xaa\x04\xb4ɦ6\xd9\xd4c1\x95_\r\x05\xf9\xe9\x96\xc4\xcf4Hy\x13Y\x99e@Y \x1c\x1c\xcb\xfd\xd9i\r!py!\xbb\x8fF\xf1\xa2r\x05\x10\xb4\xf3\xd8B\xd6\xf5JcW\x01\fLe[\xf5\xc0\xc5\xf1s1\xa7\x0fث\xe2\x04\xc0y\xb4\xdf?\xdc=}\xb3\xb9\xba\x06\xe80h&/\x99\xef\x85Ȁ\x02(\x18P\x808PZc\b\xa0#3Z\x81\x82\x12\xc8\xee\x1c\xf79G\xaf\xa6\x01\xd4\xd6E\x019 d\x05\xd9*\x03Ge\"~\r\xcavЫ\x130&/\x10텽,\x12\x1a\xf8\xc51f2[8\x88\xf8ЮV{\x92\xb1\xeb\xb4\xeb\xfbhIN\xab\xdc@\xb4\x8d\xe28\xac:<\xa2Y\x05\xda\u05ca\xf5\x81\x04\xb5Dƕ\xf2Tg\xe86w^\xd3w_\xf1Ч\xe1\xe3\x15V9\xa5\xca\n\xc2d\xf7\x17\x0f\xb9!\xfe!\x03\xa9\x1dJ}\x14\xd5\x12ř\xe8t\x95\xd8y\xfcq\xf3\x05F\xd79\x19S\xf63\xefg\xc5pNA\"\x8c\xec\x0e\xb9$qǮ\xcf6\xd1vޑ-ե\r\xa1\x9d\xd2\x1f\xe2\xb6'\tc\xed\xa6\\5\xb0Σ\b\xb6\b\xd1wJ\xb0k\xe0\xce\xc2Z\xf5h\xd6*\xe0\xff\x9e\x80\xc4t\xa8\x13\xb1\xefK\xc1\xe5\x14\x9d\n\x17\xd6.\x1e\xc61w#_\vݽ\xf1\xa8S\x06\x13\x89I\x9bv\xa4s{\xc0\xce1\xa8%\x95\xe6]H\xb2ƿ\xc42L\x92\x82f2_R\u007f\xbe\x8dfy\x9c䗃\n8\xbd\x9c`zH2S\xff\x86v\xa8O\xda`1Q\xa6\t\xbe\r%\x1d\xb4\xb1\x9f\xfb\xac\xe1\x1e_\x16n\x1fإɚ\xe7\xfa\xf5\xb9Q\x1bP\xfe7{\xb2\xb3p\xa7\x91\x15\xa9\xfc\x0f\xbb\x1c\xd5\x17\x03z0\x04\x1c\xadM};\x9b\x90\x19\xc8t\x92\xcfdH\xb0_@\xb3\x88\xe7\xce\xee\\\xde\x04Tr\xac\xa4\xf4\x13\x0e\xc9\x1e\xfc\x14\\\v\x06o纜\xf9\xf0z\x17\xa1\xe5\xe4?\xe9\u007fSN\xe3\x86\x18\x17}\xd7\x19\xd5\xe2C\xf2\xb8\xc4\xf8r\u007f\r(\xa31jk\xb0\x05\xe18\xd7.\xba\x8aY\x9d\xa6U3\x96\xday\x9fz\xa3\x80f\n\xa9O^\x0ehou\x03\xbc\xa8锿\xf2\f\xdb\xd3-\xd5\xf5\xebr8o\xa9R\xba-\xa4\xd9]\v-p\xf6.R\x16\xb3WJzq\xf3\x98\x11\xb2\xb9\x94\x1dg\xc6Uk\x8c\x8b\xc8<\x86\x9b\x10\x16\x93=\xbb\xcc滋\xf0\x828V\xfb1\xe0\xf3\xe8M\x9b\x9a\x17\xec\xee\xa7+\xee\x87\x0fW\xbbj\xfe\xd4\xcevT6t\xf8\xf5\xb7\xaaX\xc5\xeei\\0\xd3\xe5\xdf\x01\x00\x00\xff\xff\xfb\xb1p\x12\x1b\f\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4WO\x8f۶\x13\xbd\xfbS\f\x92\xc3^\"9\xc1\xef\xf0+t)\x82M\x0fA\xf3g\x11o\xf7R\xf4@\x93#\x8b]\x8aTgHm\xddO_\f)\xad\xbd\xb6\x9cl\x8aV\x17C\x149|\xf3\u07bc!\xbd\xaa\xaaj\xa5\x06{\x87\xc46\xf8\x06\xd4`\xf1ψ^\u07b8\xbe\xff\x81k\x1b\xd6\xe3\x9bս\xf5\xa6\x81\xeb\xc41\xf4_\x90C\"\x8dﰵ\xdeF\x1b\xfc\xaaǨ\x8c\x8a\xaaY\x01(\xefCT2\xcc\xf2\n\xa0\x83\x8f\x14\x9cC\xaav\xe8\xeb\xfb\xb4\xc5m\xb2\xce \xe5\xe0\xf3\xd6\xe3\xeb\xfa\xff\xf5\xeb\x15\x80&\xcc\xcbom\x8f\x1cU?4\xe0\x93s+\x00\xafzl`\f.\xf5\xc8^\r܅\xe8\x82.\x9b\xd5#:\xa4P۰\xe2\x01\xb5콣\x90\x86\x06\x0e\x1fJ\x88\tW\xc9\xe9.G\xdbL\xd1>L\xd1\xf2\x04g9\xfe\xfc\x95I\x1f,\xc7\xe8\xcdK\x9a,\xcaWO\xb0ƽT\x11G\xb2~w\xf4!\x1b\xe1+\n\x88\aJ!\x94\xa5%\x8b\x03\xd12$\xec|\xf9is\v\xf3\xd6Y\x8cS\xf63\uf1c5|\x90@\b\xb3\xbeE*\"\xb6\x14\xfa\x1c\x13\xbd\x19\x82\xf51\xbfhgџ\xd2\xcfi\xdb\xdb(\xba\xff\x91\x90\xa3hU\xc3u\xeeB\xb0EH\x83Q\x11M\r\xef=\\\xab\x1eݵb\xfc\xcf\x05\x10\xa6\xb9\x12b\x9f'\xc1q\x03=\x9d\\X;6\xd8\xd4\xde.\xe8\xb5\xec\xe4̀\xfa\x89\x81$\x8am\xed\xe4\xec6\xd0\t\xafj\xf6\xf9r\xbc\xfa\xc9\xf4e\x83C\xe9\xfe\xadݝ\x8e\x02(c\xf2١\xdc\xcdŵ_!l!\xef뼓\x14j\x1bH\x10\x8d\xd6 Us\x9e\x13\x92DS\xc2\x16\x9d\xe1\xfa,\xe4\x05\xces*\x84F4V\xee\x1c\xe8S$\x8f\x13\xf3᧬/\x94\x1f\x02\xe4ң~\xea\xb1>\xa27\xb9\xa9\x9f\xa1\t\xb9\x86\x19\r<\xd8\xd8\x15s\xb8\xe3C\xeay*\xc8s\x8f\xfb\xa5\xe1\x13\xec\xb7\x1d\xca\xcc\xd2N\x11\x185a\x14\x1c\x8cN\xcc+ά\x01>&\xce\xf6R\x8b\x11AZ\x845\xf3\xea{ܟ\x13\r\xdf\x12w:\xef\xbf\r\xf9J\xce\xc5\x190a\x8b\x84>.Z\\\xee\x1e\xe41bv\xb9\t\x9a\xc5\xe0\x1a\x87\xc8\xeb0\"\x8d\x16\x1f\xd6\x0f\x81\xee\xad\xdfUBxU\n\x81\xd7\xf9ް~\x99\u007f.\xa4|\xfb\xf9\xdd\xe7\x06\xde\x1a\x03!vH\xa2Z\x9b\xdc\\hG\xa7ݫ\xdcq_A\xb2\xe6ǫ\u007f\xc2K\x18\x8as\x9e\xc1\xcd&W\xff^N\xee\fJ(\xda\x14U\x02\x81\xf4M\x11\xbb\x9f\xd4,\xfda\xa9\x10gL\xdb\x10\x1c\xaa\xf3ғ\xeek\t\xcd9\xa4Jv\xf8\x1e\x9b\xcd\xce\xfd\x86\xc9n\xa6ibx\xc9j^6\x17B\xb9\x97\xe4[\x8a\xda\xe1%\xa3/p\xbc\x9cJ\xf5\xb8\xc1\xb3ZtT1\xf1\xf77\xe9\xbcl\x9a\xb9\x9d\x1a\xb5N$\x05=\xc5\\\xb8\xd0\xfc;\x8dz\xe8\x14/\xb8\xed\x19\xa8od\xe5,\x83\xb3-\xea\xbdvX\x02Bh\x17\xaa\xe9\xbb ˃>\xf5K\xa5\xf5vT֩\xadÅo\xbfxu\xf1\xebE\xf1\x17\xf5<\x1bd\xb9\xb5\x98\x06\"\xa5\x12{\xaa\xb2i䠾\xd2\xd2\\\xd0|:\xfd\xdb\xf1\xe2œ\u007f\x0e\xf9U\a_\xceDn\xe0\xd7\xdfV%*\x9a\xbb\xf9\xa2/\x83\u007f\a\x00\x00\xff\xff\xe4\xf3S\x85\xb2\r\x00\x00"), } diff --git a/internal/resourcepolicies/resource_policies.go b/internal/resourcepolicies/resource_policies.go index 9fe2b5642..c50133806 100644 --- a/internal/resourcepolicies/resource_policies.go +++ b/internal/resourcepolicies/resource_policies.go @@ -10,7 +10,11 @@ import ( type VolumeActionType string -const Skip VolumeActionType = "skip" +const ( + // currently only support configmap type of resource config + ConfigmapRefType string = "configmap" + Skip VolumeActionType = "skip" +) // Action defined as one action for a specific way of backup type Action struct { @@ -20,33 +24,30 @@ type Action struct { Parameters map[string]interface{} `yaml:"parameters,omitempty"` } -// VolumePolicy defined policy to conditions to match Volumes and related action to handle matched Volumes -type VolumePolicy struct { +// volumePolicy defined policy to conditions to match Volumes and related action to handle matched Volumes +type volumePolicy struct { // Conditions defined list of conditions to match Volumes Conditions map[string]interface{} `yaml:"conditions"` Action Action `yaml:"action"` } -// currently only support configmap type of resource config -const ConfigmapRefType string = "configmap" - // resourcePolicies currently defined slice of volume policies to handle backup type resourcePolicies struct { Version string `yaml:"version"` - VolumePolicies []VolumePolicy `yaml:"volumePolicies"` + VolumePolicies []volumePolicy `yaml:"volumePolicies"` // we may support other resource policies in the future, and they could be added separately - // OtherResourcePolicies: []OtherResourcePolicy + // OtherResourcePolicies []OtherResourcePolicy } type Policies struct { - Version string - VolumePolicies []volumePolicy + version string + volumePolicies []volPolicy // OtherPolicies } -func unmarshalResourcePolicies(YamlData *string) (*resourcePolicies, error) { +func unmarshalResourcePolicies(yamlData *string) (*resourcePolicies, error) { resPolicies := &resourcePolicies{} - if err := decodeStruct(strings.NewReader(*YamlData), resPolicies); err != nil { + if err := decodeStruct(strings.NewReader(*yamlData), resPolicies); err != nil { return nil, fmt.Errorf("failed to decode yaml data into resource policies %v", err) } else { return resPolicies, nil @@ -57,59 +58,68 @@ func (policies *Policies) buildPolicy(resPolicies *resourcePolicies) error { for _, vp := range resPolicies.VolumePolicies { con, err := unmarshalVolConditions(vp.Conditions) if err != nil { - return errors.Wrap(err, "failed to unmarshl volume conditions") + return errors.WithStack(err) } volCap, err := parseCapacity(con.Capacity) if err != nil { - return errors.Wrapf(err, "failed to parse condition capacity %s", con.Capacity) + return errors.WithStack(err) } - var p volumePolicy + var p volPolicy p.action = vp.Action p.conditions = append(p.conditions, &capacityCondition{capacity: *volCap}) p.conditions = append(p.conditions, &storageClassCondition{storageClass: con.StorageClass}) p.conditions = append(p.conditions, &nfsCondition{nfs: con.NFS}) p.conditions = append(p.conditions, &csiCondition{csi: con.CSI}) - policies.VolumePolicies = append(policies.VolumePolicies, p) + policies.volumePolicies = append(policies.volumePolicies, p) } // Other resource policies - policies.Version = resPolicies.Version + policies.version = resPolicies.Version return nil } -func (p *Policies) Match(res interface{}) *Action { - vol, ok := res.(*StructuredVolume) - if ok { - for _, policy := range p.VolumePolicies { - isAllMatch := false - for _, con := range policy.conditions { - if !con.Match(vol) { - isAllMatch = false - break - } - isAllMatch = true - } - if isAllMatch { - return &policy.action +func (p *Policies) match(res *structuredVolume) *Action { + for _, policy := range p.volumePolicies { + isAllMatch := false + for _, con := range policy.conditions { + if !con.match(res) { + isAllMatch = false + break } + isAllMatch = true + } + if isAllMatch { + return &policy.action } } return nil } +func (p *Policies) GetMatchAction(res interface{}) (*Action, error) { + structuredVolume := new(structuredVolume) + if pv, ok := res.(*v1.PersistentVolume); ok { + structuredVolume.parsePV(pv) + } else if volume, ok := res.(*v1.Volume); ok { + structuredVolume.parsePodVolume(volume) + } else { + return nil, errors.Errorf("failed to convert object") + } + return p.match(structuredVolume), nil +} + func (p *Policies) Validate() error { - if p.Version != currentSupportDataVersion { - return fmt.Errorf("incompatible version number %s with supported version %s", p.Version, currentSupportDataVersion) + if p.version != currentSupportDataVersion { + return fmt.Errorf("incompatible version number %s with supported version %s", p.version, currentSupportDataVersion) } - for _, policy := range p.VolumePolicies { - if err := policy.action.Validate(); err != nil { - return errors.Wrap(err, "failed to validate config") + for _, policy := range p.volumePolicies { + if err := policy.action.validate(); err != nil { + return errors.WithStack(err) } for _, con := range policy.conditions { - if err := con.Validate(); err != nil { - return errors.Wrap(err, "failed to validate conditions config") + if err := con.validate(); err != nil { + return errors.WithStack(err) } } } diff --git a/internal/resourcepolicies/resource_policies_test.go b/internal/resourcepolicies/resource_policies_test.go index 83e1c2488..846adb2b5 100644 --- a/internal/resourcepolicies/resource_policies_test.go +++ b/internal/resourcepolicies/resource_policies_test.go @@ -108,7 +108,7 @@ func TestLoadResourcePolicies(t *testing.T) { func TestGetResourceMatchedAction(t *testing.T) { resPolicies := &resourcePolicies{ Version: "v1", - VolumePolicies: []VolumePolicy{ + VolumePolicies: []volumePolicy{ { Action: Action{Type: "skip"}, Conditions: map[string]interface{}{ @@ -145,12 +145,12 @@ func TestGetResourceMatchedAction(t *testing.T) { } testCases := []struct { name string - volume *StructuredVolume + volume *structuredVolume expectedAction *Action }{ { name: "match policy", - volume: &StructuredVolume{ + volume: &structuredVolume{ capacity: *resource.NewQuantity(5<<30, resource.BinarySI), storageClass: "ebs-sc", csi: &csiVolumeSource{Driver: "aws.efs.csi.driver"}, @@ -159,7 +159,7 @@ func TestGetResourceMatchedAction(t *testing.T) { }, { name: "both matches return the first policy", - volume: &StructuredVolume{ + volume: &structuredVolume{ capacity: *resource.NewQuantity(50<<30, resource.BinarySI), storageClass: "ebs-sc", csi: &csiVolumeSource{Driver: "aws.efs.csi.driver"}, @@ -168,7 +168,7 @@ func TestGetResourceMatchedAction(t *testing.T) { }, { name: "dismatch all policies", - volume: &StructuredVolume{ + volume: &structuredVolume{ capacity: *resource.NewQuantity(50<<30, resource.BinarySI), storageClass: "ebs-sc", nfs: &nFSVolumeSource{}, @@ -185,7 +185,7 @@ func TestGetResourceMatchedAction(t *testing.T) { t.Errorf("Failed to build policy with error %v", err) } - action := policies.Match(tc.volume) + action := policies.match(tc.volume) if action == nil { if tc.expectedAction != nil { t.Errorf("Expected action %v, but got result nil", tc.expectedAction.Type) @@ -220,11 +220,11 @@ func TestGetResourcePoliciesFromConfig(t *testing.T) { assert.Nil(t, err) // Check that the returned resourcePolicies object contains the expected data - assert.Equal(t, "v1", resPolicies.Version) - assert.Len(t, resPolicies.VolumePolicies, 1) + assert.Equal(t, "v1", resPolicies.version) + assert.Len(t, resPolicies.volumePolicies, 1) policies := resourcePolicies{ Version: "v1", - VolumePolicies: []VolumePolicy{ + VolumePolicies: []volumePolicy{ { Conditions: map[string]interface{}{ "capacity": "0,10Gi", diff --git a/internal/resourcepolicies/volume_resources.go b/internal/resourcepolicies/volume_resources.go index 0f8fae0a1..fcf8c0def 100644 --- a/internal/resourcepolicies/volume_resources.go +++ b/internal/resourcepolicies/volume_resources.go @@ -11,30 +11,30 @@ import ( "k8s.io/apimachinery/pkg/api/resource" ) -type volumePolicy struct { +type volPolicy struct { action Action - conditions []VolumeCondition + conditions []volumeCondition } -type VolumeCondition interface { - Match(v *StructuredVolume) bool - Validate() error +type volumeCondition interface { + match(v *structuredVolume) bool + validate() error } -// Capacity consist of the lower and upper boundary -type Capacity struct { +// capacity consist of the lower and upper boundary +type capacity struct { lower resource.Quantity upper resource.Quantity } -type StructuredVolume struct { +type structuredVolume struct { capacity resource.Quantity storageClass string nfs *nFSVolumeSource csi *csiVolumeSource } -func (s *StructuredVolume) ParsePV(pv *corev1api.PersistentVolume) { +func (s *structuredVolume) parsePV(pv *corev1api.PersistentVolume) { s.capacity = *pv.Spec.Capacity.Storage() s.storageClass = pv.Spec.StorageClassName nfs := pv.Spec.NFS @@ -48,7 +48,7 @@ func (s *StructuredVolume) ParsePV(pv *corev1api.PersistentVolume) { } } -func (s *StructuredVolume) ParsePodVolume(vol *corev1api.Volume) { +func (s *structuredVolume) parsePodVolume(vol *corev1api.Volume) { nfs := vol.NFS if nfs != nil { s.nfs = &nFSVolumeSource{Server: nfs.Server, Path: nfs.Path} @@ -61,10 +61,10 @@ func (s *StructuredVolume) ParsePodVolume(vol *corev1api.Volume) { } type capacityCondition struct { - capacity Capacity + capacity capacity } -func (c *capacityCondition) Match(v *StructuredVolume) bool { +func (c *capacityCondition) match(v *structuredVolume) bool { return c.capacity.isInRange(v.capacity) } @@ -72,7 +72,7 @@ type storageClassCondition struct { storageClass []string } -func (s *storageClassCondition) Match(v *StructuredVolume) bool { +func (s *storageClassCondition) match(v *structuredVolume) bool { if len(s.storageClass) == 0 { return true } @@ -94,7 +94,7 @@ type nfsCondition struct { nfs *nFSVolumeSource } -func (c *nfsCondition) Match(v *StructuredVolume) bool { +func (c *nfsCondition) match(v *structuredVolume) bool { if c.nfs == nil { return true } @@ -128,7 +128,7 @@ type csiCondition struct { csi *csiVolumeSource } -func (c *csiCondition) Match(v *StructuredVolume) bool { +func (c *csiCondition) match(v *structuredVolume) bool { if c.csi == nil { return true } @@ -141,14 +141,14 @@ func (c *csiCondition) Match(v *StructuredVolume) bool { } // parseCapacity parse string into capacity format -func parseCapacity(capacity string) (*Capacity, error) { - if capacity == "" { - capacity = "," +func parseCapacity(cap string) (*capacity, error) { + if cap == "" { + cap = "," } - capacities := strings.Split(capacity, ",") + capacities := strings.Split(cap, ",") var quantities []resource.Quantity if len(capacities) != 2 { - return nil, fmt.Errorf("wrong format of Capacity %v", capacity) + return nil, fmt.Errorf("wrong format of Capacity %v", cap) } else { for _, v := range capacities { if strings.TrimSpace(v) == "" { @@ -164,11 +164,11 @@ func parseCapacity(capacity string) (*Capacity, error) { } } } - return &Capacity{lower: quantities[0], upper: quantities[1]}, nil + return &capacity{lower: quantities[0], upper: quantities[1]}, nil } // isInRange returns true if the quantity y is in range of capacity, or it returns false -func (c *Capacity) isInRange(y resource.Quantity) bool { +func (c *capacity) isInRange(y resource.Quantity) bool { if c.lower.IsZero() && c.upper.Cmp(y) >= 0 { // [0, a] y return true diff --git a/internal/resourcepolicies/volume_resources_test.go b/internal/resourcepolicies/volume_resources_test.go index c3e967ba2..66d799669 100644 --- a/internal/resourcepolicies/volume_resources_test.go +++ b/internal/resourcepolicies/volume_resources_test.go @@ -10,8 +10,8 @@ import ( "k8s.io/apimachinery/pkg/api/resource" ) -func setStructuredVolume(capacity resource.Quantity, sc string, nfs *nFSVolumeSource, csi *csiVolumeSource) *StructuredVolume { - return &StructuredVolume{ +func setStructuredVolume(capacity resource.Quantity, sc string, nfs *nFSVolumeSource, csi *csiVolumeSource) *structuredVolume { + return &structuredVolume{ capacity: capacity, storageClass: sc, nfs: nfs, @@ -20,14 +20,14 @@ func setStructuredVolume(capacity resource.Quantity, sc string, nfs *nFSVolumeSo } func TestParseCapacity(t *testing.T) { - var emptyCapacity Capacity + var emptyCapacity capacity tests := []struct { input string - expected Capacity + expected capacity expectedErr error }{ - {"10Gi,20Gi", Capacity{lower: *resource.NewQuantity(10<<30, resource.BinarySI), upper: *resource.NewQuantity(20<<30, resource.BinarySI)}, nil}, - {"10Gi,", Capacity{lower: *resource.NewQuantity(10<<30, resource.BinarySI), upper: *resource.NewQuantity(0, resource.DecimalSI)}, nil}, + {"10Gi,20Gi", capacity{lower: *resource.NewQuantity(10<<30, resource.BinarySI), upper: *resource.NewQuantity(20<<30, resource.BinarySI)}, nil}, + {"10Gi,", capacity{lower: *resource.NewQuantity(10<<30, resource.BinarySI), upper: *resource.NewQuantity(0, resource.DecimalSI)}, nil}, {"10Gi", emptyCapacity, fmt.Errorf("wrong format of Capacity 10Gi")}, {"", emptyCapacity, nil}, } @@ -49,18 +49,18 @@ func TestCapacityIsInRange(t *testing.T) { t.Parallel() tests := []struct { - capacity *Capacity + capacity *capacity quantity resource.Quantity isInRange bool }{ - {&Capacity{*resource.NewQuantity(0, resource.BinarySI), *resource.NewQuantity(10<<30, resource.BinarySI)}, *resource.NewQuantity(5<<30, resource.BinarySI), true}, - {&Capacity{*resource.NewQuantity(0, resource.BinarySI), *resource.NewQuantity(10<<30, resource.BinarySI)}, *resource.NewQuantity(15<<30, resource.BinarySI), false}, - {&Capacity{*resource.NewQuantity(20<<30, resource.BinarySI), *resource.NewQuantity(0, resource.DecimalSI)}, *resource.NewQuantity(25<<30, resource.BinarySI), true}, - {&Capacity{*resource.NewQuantity(20<<30, resource.BinarySI), *resource.NewQuantity(0, resource.DecimalSI)}, *resource.NewQuantity(15<<30, resource.BinarySI), false}, - {&Capacity{*resource.NewQuantity(10<<30, resource.BinarySI), *resource.NewQuantity(20<<30, resource.BinarySI)}, *resource.NewQuantity(15<<30, resource.BinarySI), true}, - {&Capacity{*resource.NewQuantity(10<<30, resource.BinarySI), *resource.NewQuantity(20<<30, resource.BinarySI)}, *resource.NewQuantity(5<<30, resource.BinarySI), false}, - {&Capacity{*resource.NewQuantity(10<<30, resource.BinarySI), *resource.NewQuantity(20<<30, resource.BinarySI)}, *resource.NewQuantity(25<<30, resource.BinarySI), false}, - {&Capacity{*resource.NewQuantity(0, resource.BinarySI), *resource.NewQuantity(0, resource.BinarySI)}, *resource.NewQuantity(5<<30, resource.BinarySI), true}, + {&capacity{*resource.NewQuantity(0, resource.BinarySI), *resource.NewQuantity(10<<30, resource.BinarySI)}, *resource.NewQuantity(5<<30, resource.BinarySI), true}, + {&capacity{*resource.NewQuantity(0, resource.BinarySI), *resource.NewQuantity(10<<30, resource.BinarySI)}, *resource.NewQuantity(15<<30, resource.BinarySI), false}, + {&capacity{*resource.NewQuantity(20<<30, resource.BinarySI), *resource.NewQuantity(0, resource.DecimalSI)}, *resource.NewQuantity(25<<30, resource.BinarySI), true}, + {&capacity{*resource.NewQuantity(20<<30, resource.BinarySI), *resource.NewQuantity(0, resource.DecimalSI)}, *resource.NewQuantity(15<<30, resource.BinarySI), false}, + {&capacity{*resource.NewQuantity(10<<30, resource.BinarySI), *resource.NewQuantity(20<<30, resource.BinarySI)}, *resource.NewQuantity(15<<30, resource.BinarySI), true}, + {&capacity{*resource.NewQuantity(10<<30, resource.BinarySI), *resource.NewQuantity(20<<30, resource.BinarySI)}, *resource.NewQuantity(5<<30, resource.BinarySI), false}, + {&capacity{*resource.NewQuantity(10<<30, resource.BinarySI), *resource.NewQuantity(20<<30, resource.BinarySI)}, *resource.NewQuantity(25<<30, resource.BinarySI), false}, + {&capacity{*resource.NewQuantity(0, resource.BinarySI), *resource.NewQuantity(0, resource.BinarySI)}, *resource.NewQuantity(5<<30, resource.BinarySI), true}, } for _, test := range tests { @@ -80,7 +80,7 @@ func TestStorageClassConditionMatch(t *testing.T) { tests := []struct { name string condition *storageClassCondition - volume *StructuredVolume + volume *structuredVolume expectedMatch bool }{ { @@ -117,7 +117,7 @@ func TestStorageClassConditionMatch(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - match := tt.condition.Match(tt.volume) + match := tt.condition.match(tt.volume) if match != tt.expectedMatch { t.Errorf("expected %v, but got %v", tt.expectedMatch, match) } @@ -130,7 +130,7 @@ func TestNFSConditionMatch(t *testing.T) { tests := []struct { name string condition *nfsCondition - volume *StructuredVolume + volume *structuredVolume expectedMatch bool }{ { @@ -172,7 +172,7 @@ func TestNFSConditionMatch(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - match := tt.condition.Match(tt.volume) + match := tt.condition.match(tt.volume) if match != tt.expectedMatch { t.Errorf("expected %v, but got %v", tt.expectedMatch, match) } @@ -185,7 +185,7 @@ func TestCSIConditionMatch(t *testing.T) { tests := []struct { name string condition *csiCondition - volume *StructuredVolume + volume *structuredVolume expectedMatch bool }{ { @@ -209,7 +209,7 @@ func TestCSIConditionMatch(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - match := tt.condition.Match(tt.volume) + match := tt.condition.match(tt.volume) if match != tt.expectedMatch { t.Errorf("expected %v, but got %v", tt.expectedMatch, match) } @@ -322,8 +322,8 @@ func TestParsePodVolume(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { // Call the function - structuredVolume := &StructuredVolume{} - structuredVolume.ParsePodVolume(tc.inputVolume) + structuredVolume := &structuredVolume{} + structuredVolume.parsePodVolume(tc.inputVolume) // Check the results if tc.expectedNFS != nil { @@ -384,11 +384,11 @@ func TestParsePV(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { // Call the function - structuredVolume := &StructuredVolume{} - structuredVolume.ParsePV(tc.inputVolume) + structuredVolume := &structuredVolume{} + structuredVolume.parsePV(tc.inputVolume) // Check the results if structuredVolume.capacity != *tc.inputVolume.Spec.Capacity.Storage() { - t.Errorf("Capacity does not match expected value") + t.Errorf("capacity does not match expected value") } if structuredVolume.storageClass != tc.inputVolume.Spec.StorageClassName { t.Errorf("Storage class does not match expected value") diff --git a/internal/resourcepolicies/volume_resources_validator.go b/internal/resourcepolicies/volume_resources_validator.go index a9b5f6e3a..a6597a3f9 100644 --- a/internal/resourcepolicies/volume_resources_validator.go +++ b/internal/resourcepolicies/volume_resources_validator.go @@ -29,7 +29,7 @@ type volumeConditions struct { CSI *csiVolumeSource `yaml:"csi,omitempty"` } -func (c *capacityCondition) Validate() error { +func (c *capacityCondition) validate() error { // [0, a] // [a, b] // [b, 0] @@ -42,17 +42,17 @@ func (c *capacityCondition) Validate() error { } -func (s *storageClassCondition) Validate() error { +func (s *storageClassCondition) validate() error { // validate by yamlv3 return nil } -func (c *nfsCondition) Validate() error { +func (c *nfsCondition) validate() error { // validate by yamlv3 return nil } -func (c *csiCondition) Validate() error { +func (c *csiCondition) validate() error { // validate by yamlv3 return nil } @@ -64,9 +64,9 @@ func decodeStruct(r io.Reader, s interface{}) error { return dec.Decode(s) } -// Validate check action format -func (a *Action) Validate() error { - // Validate Type +// validate check action format +func (a *Action) validate() error { + // validate Type if a.Type != Skip { return fmt.Errorf("invalid action type %s", a.Type) } diff --git a/internal/resourcepolicies/volume_resources_validator_test.go b/internal/resourcepolicies/volume_resources_validator_test.go index a18e48513..92fd9a60b 100644 --- a/internal/resourcepolicies/volume_resources_validator_test.go +++ b/internal/resourcepolicies/volume_resources_validator_test.go @@ -9,47 +9,47 @@ import ( func TestCapacityConditionValidate(t *testing.T) { testCases := []struct { name string - capacity *Capacity + capacity *capacity wantErr bool }{ { name: "lower and upper are both zero", - capacity: &Capacity{lower: *resource.NewQuantity(0, resource.DecimalSI), upper: *resource.NewQuantity(0, resource.DecimalSI)}, + capacity: &capacity{lower: *resource.NewQuantity(0, resource.DecimalSI), upper: *resource.NewQuantity(0, resource.DecimalSI)}, wantErr: false, }, { name: "lower is zero and upper is greater than zero", - capacity: &Capacity{lower: *resource.NewQuantity(0, resource.DecimalSI), upper: *resource.NewQuantity(100, resource.DecimalSI)}, + capacity: &capacity{lower: *resource.NewQuantity(0, resource.DecimalSI), upper: *resource.NewQuantity(100, resource.DecimalSI)}, wantErr: false, }, { name: "lower is greater than upper", - capacity: &Capacity{lower: *resource.NewQuantity(100, resource.DecimalSI), upper: *resource.NewQuantity(50, resource.DecimalSI)}, + capacity: &capacity{lower: *resource.NewQuantity(100, resource.DecimalSI), upper: *resource.NewQuantity(50, resource.DecimalSI)}, wantErr: true, }, { name: "lower and upper are equal", - capacity: &Capacity{lower: *resource.NewQuantity(100, resource.DecimalSI), upper: *resource.NewQuantity(100, resource.DecimalSI)}, + capacity: &capacity{lower: *resource.NewQuantity(100, resource.DecimalSI), upper: *resource.NewQuantity(100, resource.DecimalSI)}, wantErr: false, }, { name: "lower is greater than zero and upper is zero", - capacity: &Capacity{lower: *resource.NewQuantity(100, resource.DecimalSI), upper: *resource.NewQuantity(0, resource.DecimalSI)}, + capacity: &capacity{lower: *resource.NewQuantity(100, resource.DecimalSI), upper: *resource.NewQuantity(0, resource.DecimalSI)}, wantErr: false, }, { name: "lower and upper are both not zero and lower is less than upper", - capacity: &Capacity{lower: *resource.NewQuantity(100, resource.DecimalSI), upper: *resource.NewQuantity(200, resource.DecimalSI)}, + capacity: &capacity{lower: *resource.NewQuantity(100, resource.DecimalSI), upper: *resource.NewQuantity(200, resource.DecimalSI)}, wantErr: false, }, { name: "lower and upper are both not zero and lower is equal to upper", - capacity: &Capacity{lower: *resource.NewQuantity(100, resource.DecimalSI), upper: *resource.NewQuantity(100, resource.DecimalSI)}, + capacity: &capacity{lower: *resource.NewQuantity(100, resource.DecimalSI), upper: *resource.NewQuantity(100, resource.DecimalSI)}, wantErr: false, }, { name: "lower and upper are both not zero and lower is greater than upper", - capacity: &Capacity{lower: *resource.NewQuantity(200, resource.DecimalSI), upper: *resource.NewQuantity(100, resource.DecimalSI)}, + capacity: &capacity{lower: *resource.NewQuantity(200, resource.DecimalSI), upper: *resource.NewQuantity(100, resource.DecimalSI)}, wantErr: true, }, } @@ -57,7 +57,7 @@ func TestCapacityConditionValidate(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { c := &capacityCondition{capacity: *tc.capacity} - err := c.Validate() + err := c.validate() if (err != nil) != tc.wantErr { t.Fatalf("Expected error %v, but got error %v", tc.wantErr, err) @@ -76,7 +76,7 @@ func TestValidate(t *testing.T) { name: "unknown key in yaml", res: &resourcePolicies{ Version: "v1", - VolumePolicies: []VolumePolicy{ + VolumePolicies: []volumePolicy{ { Action: Action{Type: "skip"}, Conditions: map[string]interface{}{ @@ -97,7 +97,7 @@ func TestValidate(t *testing.T) { name: "error format of capacity", res: &resourcePolicies{ Version: "v1", - VolumePolicies: []VolumePolicy{ + VolumePolicies: []volumePolicy{ { Action: Action{Type: "skip"}, Conditions: map[string]interface{}{ @@ -117,7 +117,7 @@ func TestValidate(t *testing.T) { name: "error format of storageClass", res: &resourcePolicies{ Version: "v1", - VolumePolicies: []VolumePolicy{ + VolumePolicies: []volumePolicy{ { Action: Action{Type: "skip"}, Conditions: map[string]interface{}{ @@ -137,7 +137,7 @@ func TestValidate(t *testing.T) { name: "error format of csi", res: &resourcePolicies{ Version: "v1", - VolumePolicies: []VolumePolicy{ + VolumePolicies: []volumePolicy{ { Action: Action{Type: "skip"}, Conditions: map[string]interface{}{ @@ -154,7 +154,7 @@ func TestValidate(t *testing.T) { name: "unsupported version", res: &resourcePolicies{ Version: "v2", - VolumePolicies: []VolumePolicy{ + VolumePolicies: []volumePolicy{ { Action: Action{Type: "skip"}, Conditions: map[string]interface{}{ @@ -173,7 +173,7 @@ func TestValidate(t *testing.T) { name: "unsupported action", res: &resourcePolicies{ Version: "v1", - VolumePolicies: []VolumePolicy{ + VolumePolicies: []volumePolicy{ { Action: Action{Type: "unsupported"}, Conditions: map[string]interface{}{ @@ -192,7 +192,7 @@ func TestValidate(t *testing.T) { name: "error format of nfs", res: &resourcePolicies{ Version: "v1", - VolumePolicies: []VolumePolicy{ + VolumePolicies: []volumePolicy{ { Action: Action{Type: "skip"}, Conditions: map[string]interface{}{ @@ -209,7 +209,7 @@ func TestValidate(t *testing.T) { name: "supported formart volume policies", res: &resourcePolicies{ Version: "v1", - VolumePolicies: []VolumePolicy{ + VolumePolicies: []volumePolicy{ { Action: Action{Type: "skip"}, Conditions: map[string]interface{}{ diff --git a/pkg/apis/velero/v1/backup_types.go b/pkg/apis/velero/v1/backup_types.go index 190b5a953..b6e27fd89 100644 --- a/pkg/apis/velero/v1/backup_types.go +++ b/pkg/apis/velero/v1/backup_types.go @@ -160,9 +160,9 @@ type BackupSpec struct { // The default value is 1 hour. // +optional ItemOperationTimeout metav1.Duration `json:"itemOperationTimeout,omitempty"` - // ResourcePolicies specifies the referenced resource policies that backup should follow + // ResourcePolicy specifies the referenced resource policies that backup should follow // +optional - ResourcePolicies *v1.TypedLocalObjectReference `json:"resourcePolices,omitempty"` + ResourcePolicy *v1.TypedLocalObjectReference `json:"resourcePolicy,omitempty"` } // BackupHooks contains custom behaviors that should be executed at different phases of the backup. diff --git a/pkg/apis/velero/v1/zz_generated.deepcopy.go b/pkg/apis/velero/v1/zz_generated.deepcopy.go index 803adb2d6..0d0637a12 100644 --- a/pkg/apis/velero/v1/zz_generated.deepcopy.go +++ b/pkg/apis/velero/v1/zz_generated.deepcopy.go @@ -371,8 +371,8 @@ func (in *BackupSpec) DeepCopyInto(out *BackupSpec) { } out.CSISnapshotTimeout = in.CSISnapshotTimeout out.ItemOperationTimeout = in.ItemOperationTimeout - if in.ResourcePolicies != nil { - in, out := &in.ResourcePolicies, &out.ResourcePolicies + if in.ResourcePolicy != nil { + in, out := &in.ResourcePolicy, &out.ResourcePolicy *out = new(corev1.TypedLocalObjectReference) (*in).DeepCopyInto(*out) } diff --git a/pkg/backup/item_backupper.go b/pkg/backup/item_backupper.go index fd22ea02c..3ce274f78 100644 --- a/pkg/backup/item_backupper.go +++ b/pkg/backup/item_backupper.go @@ -324,7 +324,7 @@ func (ib *itemBackupper) executeActions( } log.Info("Executing custom action") - if act, err := ib.checkResourcePolicies(obj, &groupResource, action.Name()); err != nil { + if act, err := ib.getMatchAction(obj, groupResource, action.Name()); err != nil { return nil, itemFiles, errors.WithStack(err) } else if act != nil && act.Type == resourcepolicies.Skip { log.Infof("skip snapshot of pvc %s/%s bound pv for the matched resource policies", namespace, name) @@ -484,10 +484,10 @@ func (ib *itemBackupper) takePVSnapshot(obj runtime.Unstructured, log logrus.Fie } if ib.backupRequest.ResPolicies != nil { - structuredVolume := &resourcepolicies.StructuredVolume{} - structuredVolume.ParsePV(pv) - action := ib.backupRequest.ResPolicies.Match(structuredVolume) - if action != nil && action.Type == resourcepolicies.Skip { + if action, err := ib.backupRequest.ResPolicies.GetMatchAction(pv); err != nil { + log.WithError(err).Errorf("Error getting matched resource policies for pv %s", pv.Name) + return nil + } else if action != nil && action.Type == resourcepolicies.Skip { log.Infof("skip snapshot of pv %s for the matched resource policies", pv.Name) return nil } @@ -579,8 +579,8 @@ func (ib *itemBackupper) takePVSnapshot(obj runtime.Unstructured, log logrus.Fie return kubeerrs.NewAggregate(errs) } -func (ib *itemBackupper) checkResourcePolicies(obj runtime.Unstructured, groupResource *schema.GroupResource, actionName string) (*resourcepolicies.Action, error) { - if ib.backupRequest.ResPolicies != nil && groupResource.String() == "persistentvolumeclaims" && actionName == "velero.io/csi-pvc-backupper" { +func (ib *itemBackupper) getMatchAction(obj runtime.Unstructured, groupResource schema.GroupResource, backupItemActionName string) (*resourcepolicies.Action, error) { + if ib.backupRequest.ResPolicies != nil && groupResource == kuberesource.PersistentVolumeClaims && backupItemActionName == "velero.io/csi-pvc-backupper" { pvc := corev1api.PersistentVolumeClaim{} if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &pvc); err != nil { return nil, errors.WithStack(err) @@ -595,10 +595,7 @@ func (ib *itemBackupper) checkResourcePolicies(obj runtime.Unstructured, groupRe if err := ib.kbClient.Get(context.Background(), kbClient.ObjectKey{Name: pvName}, pv); err != nil { return nil, errors.WithStack(err) } - - volume := resourcepolicies.StructuredVolume{} - volume.ParsePV(pv) - return ib.backupRequest.ResPolicies.Match(&volume), nil + return ib.backupRequest.ResPolicies.GetMatchAction(pv) } return nil, nil } diff --git a/pkg/builder/backup_builder.go b/pkg/builder/backup_builder.go index d42eb7e50..851bfa010 100644 --- a/pkg/builder/backup_builder.go +++ b/pkg/builder/backup_builder.go @@ -125,8 +125,8 @@ func (b *BackupBuilder) FromSchedule(schedule *velerov1api.Schedule) *BackupBuil }) } - if schedule.Spec.Template.ResourcePolicies != nil { - b.ResourcePolicies(schedule.Spec.Template.ResourcePolicies.Name) + if schedule.Spec.Template.ResourcePolicy != nil { + b.ResourcePolicies(schedule.Spec.Template.ResourcePolicy.Name) } return b @@ -282,8 +282,8 @@ func (b *BackupBuilder) ItemOperationTimeout(timeout time.Duration) *BackupBuild return b } -// resourcePolicies sets the Backup's resource polices. +// ResourcePolicies sets the Backup's resource polices. func (b *BackupBuilder) ResourcePolicies(name string) *BackupBuilder { - b.object.Spec.ResourcePolicies = &v1.TypedLocalObjectReference{Kind: resourcepolicies.ConfigmapRefType, Name: name} + b.object.Spec.ResourcePolicy = &v1.TypedLocalObjectReference{Kind: resourcepolicies.ConfigmapRefType, Name: name} return b } diff --git a/pkg/cmd/cli/schedule/create.go b/pkg/cmd/cli/schedule/create.go index 1538f093a..ee3b016ca 100644 --- a/pkg/cmd/cli/schedule/create.go +++ b/pkg/cmd/cli/schedule/create.go @@ -161,7 +161,7 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { } if o.BackupOptions.ResPoliciesConfigmap != "" { - schedule.Spec.Template.ResourcePolicies = &v1.TypedLocalObjectReference{Kind: resourcepolicies.ConfigmapRefType, Name: o.BackupOptions.ResPoliciesConfigmap} + schedule.Spec.Template.ResourcePolicy = &v1.TypedLocalObjectReference{Kind: resourcepolicies.ConfigmapRefType, Name: o.BackupOptions.ResPoliciesConfigmap} } if printed, err := output.PrintWithFormat(c, schedule); printed || err != nil { diff --git a/pkg/controller/backup_controller.go b/pkg/controller/backup_controller.go index cc532683c..41e5cec01 100644 --- a/pkg/controller/backup_controller.go +++ b/pkg/controller/backup_controller.go @@ -460,17 +460,17 @@ func (b *backupReconciler) prepareBackupRequest(backup *velerov1api.Backup, logg request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("encountered labelSelector as well as orLabelSelectors in backup spec, only one can be specified")) } - if request.Spec.ResourcePolicies != nil && request.Spec.ResourcePolicies.Kind == resourcepolicies.ConfigmapRefType { + if request.Spec.ResourcePolicy != nil && request.Spec.ResourcePolicy.Kind == resourcepolicies.ConfigmapRefType { policiesConfigmap := &v1.ConfigMap{} - err := b.kbClient.Get(context.Background(), kbclient.ObjectKey{Namespace: request.Namespace, Name: request.Spec.ResourcePolicies.Name}, policiesConfigmap) + err := b.kbClient.Get(context.Background(), kbclient.ObjectKey{Namespace: request.Namespace, Name: request.Spec.ResourcePolicy.Name}, policiesConfigmap) if err != nil { - request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("failed to get resource policies %s/%s configmap with err %v", request.Namespace, request.Spec.ResourcePolicies.Name, err)) + request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("failed to get resource policies %s/%s configmap with err %v", request.Namespace, request.Spec.ResourcePolicy.Name, err)) } res, err := resourcepolicies.GetResourcePoliciesFromConfig(policiesConfigmap) if err != nil { - request.Status.ValidationErrors = append(request.Status.ValidationErrors, errors.Wrapf(err, fmt.Sprintf("resource policies %s/%s", request.Namespace, request.Spec.ResourcePolicies.Name)).Error()) + request.Status.ValidationErrors = append(request.Status.ValidationErrors, errors.Wrapf(err, fmt.Sprintf("resource policies %s/%s", request.Namespace, request.Spec.ResourcePolicy.Name)).Error()) } else if err = res.Validate(); err != nil { - request.Status.ValidationErrors = append(request.Status.ValidationErrors, errors.Wrapf(err, fmt.Sprintf("resource policies %s/%s", request.Namespace, request.Spec.ResourcePolicies.Name)).Error()) + request.Status.ValidationErrors = append(request.Status.ValidationErrors, errors.Wrapf(err, fmt.Sprintf("resource policies %s/%s", request.Namespace, request.Spec.ResourcePolicy.Name)).Error()) } request.ResPolicies = res } diff --git a/pkg/podvolume/backupper.go b/pkg/podvolume/backupper.go index 31332f046..cc62aaaca 100644 --- a/pkg/podvolume/backupper.go +++ b/pkg/podvolume/backupper.go @@ -111,20 +111,20 @@ func resultsKey(ns, name string) string { return fmt.Sprintf("%s/%s", ns, name) } -func (b *backupper) checkResourcePolicies(resPolicies *resourcepolicies.Policies, pvc *corev1api.PersistentVolumeClaim, volume *corev1api.Volume) (*resourcepolicies.Action, error) { - structuredVolume := &resourcepolicies.StructuredVolume{} +func (b *backupper) getMatchAction(resPolicies *resourcepolicies.Policies, pvc *corev1api.PersistentVolumeClaim, volume *corev1api.Volume) (*resourcepolicies.Action, error) { if pvc != nil { pv, err := b.pvClient.PersistentVolumes().Get(context.TODO(), pvc.Spec.VolumeName, metav1.GetOptions{}) if err != nil { return nil, errors.Wrapf(err, "error getting pv for pvc %s", pvc.Spec.VolumeName) } - structuredVolume.ParsePV(pv) - } else if volume != nil { - structuredVolume.ParsePodVolume(volume) - } else { - return nil, errors.Errorf("failed to check resource policies for empty volume") + return resPolicies.GetMatchAction(pv) } - return resPolicies.Match(structuredVolume), nil + + if volume != nil { + return resPolicies.GetMatchAction(volume) + } + + return nil, errors.Errorf("failed to check resource policies for empty volume") } func (b *backupper) BackupPodVolumes(backup *velerov1api.Backup, pod *corev1api.Pod, volumesToBackup []string, resPolicies *resourcepolicies.Policies, log logrus.FieldLogger) ([]*velerov1api.PodVolumeBackup, []error) { @@ -219,7 +219,7 @@ func (b *backupper) BackupPodVolumes(backup *velerov1api.Backup, pod *corev1api. } if resPolicies != nil { - if action, err := b.checkResourcePolicies(resPolicies, pvc, &volume); err != nil { + if action, err := b.getMatchAction(resPolicies, pvc, &volume); err != nil { errs = append(errs, errors.Wrapf(err, "error getting pv for pvc %s", pvc.Spec.VolumeName)) continue } else if action != nil && action.Type == resourcepolicies.Skip {