From 454fcc8eb9dd7a9166ba2b3f7b56d57ec1a72776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Rostagni?= Date: Tue, 1 Oct 2024 17:35:06 +0200 Subject: [PATCH 1/2] Add disabled PV re-provisioning by StorageClasses option on restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Clément Rostagni --- config/crd/v1/bases/velero.io_restores.yaml | 9 + config/crd/v1/crds/crds.go | 2 +- pkg/apis/velero/v1/restore_types.go | 7 + pkg/apis/velero/v1/zz_generated.deepcopy.go | 5 + pkg/builder/restore_builder.go | 6 + pkg/cmd/cli/restore/create.go | 54 +++--- pkg/cmd/cli/restore/create_test.go | 3 + pkg/cmd/util/output/restore_describer.go | 7 + pkg/restore/restore.go | 47 ++++- pkg/restore/restore_test.go | 189 ++++++++++++++++++++ 10 files changed, 302 insertions(+), 27 deletions(-) diff --git a/config/crd/v1/bases/velero.io_restores.yaml b/config/crd/v1/bases/velero.io_restores.yaml index ce18d29bf6..74bdf00ae3 100644 --- a/config/crd/v1/bases/velero.io_restores.yaml +++ b/config/crd/v1/bases/velero.io_restores.yaml @@ -46,6 +46,15 @@ spec: BackupName is the unique name of the Velero backup to restore from. type: string + disabledPVReprovisioningStorageClasses: + description: |- + DisabledPVReprovisioningStorageClasses is a slice of StorageClasses names. + PV without snaptshot and having one of these StorageClass will not be + re-provisionned (even when ReclaimPolicy is Delete). + items: + type: string + nullable: true + type: array excludedNamespaces: description: |- ExcludedNamespaces contains a list of namespaces that are not diff --git a/config/crd/v1/crds/crds.go b/config/crd/v1/crds/crds.go index 07ed6845c8..95a36b35fe 100644 --- a/config/crd/v1/crds/crds.go +++ b/config/crd/v1/crds/crds.go @@ -36,7 +36,7 @@ var rawCRDs = [][]byte{ []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcWMs\xe36\f\xbd\xfbW`\xa6\x97vf%o\xa6=t|k\x9d=d6\xddf\xe2m\xee\x14\x05Il(\x92%Ag\xd3\xe9\x8f\uf014\xfc!ˎsY\xdd\f\x82\xe0\xc3\x03\xf0H\x17E\xb1\x10N=\xa1\x0fʚ\x15\b\xa7\xf0\x1b\xa1\xe1_\xa1|\xfe5\x94\xca.\xb77\x8bge\xea\x15\xacc \xdb?b\xb0\xd1K\xbc\xc5F\x19EʚE\x8f$jAb\xb5\x00\x10\xc6X\x12l\x0e\xfc\x13@ZC\xdej\x8d\xbehєϱ\xc2**]\xa3O\xc1ǣ\xb7\x1f˛_ʏ\v\x00#z\\Am_\x8c\xb6\xa2\xf6\xf8O\xc4@\xa1ܢFoKe\x17\xc1\xa1\xe4ح\xb7ѭ`\xbf\x90\xf7\x0e\xe7f̷C\x98\xc7\x1c&\xadh\x15\xe8\xf3\xdc\xea\xbd\x1a<\x9c\x8e^\xe8S\x10i1(\xd3F-\xfc\xc9\xf2\x02 H\xebp\x05_\x18\x86\x13\x12\xeb\x05\xc0\x90b\x82U\f\xd9mor(\xd9a/2^\x00\xeb\xd0\xfc\xf6p\xf7\xf4\xf3\xe6\xc8\fPc\x90^9JD\xfdW\xec\xec0M\x00T\x00\x01\x03\x1c \xbbC\b\u0080\xf0\xa4\x1a!\t\x1ao{\xa8\x84|\x8e\x0el\xf57J\x82@\u058b\x16?@\x88\xb2\x03\xc1Q\xb2\xc3\xc1Yڶ\xd0(\x8d\xe5\xce\xe6\xbcu\xe8I\x8d\x94\xe7\uf821\x0e\xac\x97\xb2\xe0\x8f\x13ϻ\xa0\xe6\xce\xc2\x00\xd4\xe1H\x1e\xd6\x03W`\x1b\xa0N\x05\xf0\xe8<\x064\xb9\xd7\xd8,̐M9\t\xbdA\xcfa t6\xea\x9a\x1br\x8b\x9e\xc0\xa3\xb4\xadQ\xff\xeeb\af\x8c\x0fՂ\x12\x99\x86\xd0\x1b\xa1a+t\xc4\x0f L=\x89܋W\xf0\x98\x18\x8c\xe6 ^\xda\x10\xa68\xfe\xb0\x1eA\x99Ʈ\xa0#ra\xb5\\\xb6\x8a\xc61\x93\xb6\xef\xa3Q\xf4\xbaL\x13\xa3\xaaHևe\x8d[\xd4ˠ\xdaBx\xd9)BI\xd1\xe3R8U\xa4DL\x1a\xb5\xb2\xaf\x7f\xf0\xc3`\x86\xa3c\xe9\x95\x1b2\x90W\xa6=XH\xd3\xf1\x8e\xf2\xf0\xbc\xe4\xeeʡr\x8a\xfb*\xb0\x89\xa9{\xfc\xb4\xf9\n#\x92\\\xa9\xa1\xc5v\xae'\xbc\x8c\xf5a6\x95i\xd0\xe7}\xa9M9&\x9a\xdaYe(\xfd\x90Z\xa1!\b\xb1\xea\x15\x85\xb1\u05f9tӰ\xeb$EP!DW\v\xc2z\xeapg`-z\xd4k\x11\xf0;\u05ca\xab\x12\n.\xc2U\xd5:\x14ةs\xa6\xf7`a\x94\xc73\xa5\x9dH\xc6ơ\xe4\xc22\xb7\xbcS5J\xe6\x91j\xac\a\xb1W\x90\x81\xe9c\xa2\xe6\x15 \x81\x13\xbeE\x9aZ'X\xbe&'>\xfe\xa5\x13ǂ\xf5#\x96mɚ\x13\x06 Y\x8f~\x9a\x16\xea\x12\x06\x98m\xf4Y$c\x7f3\r\xcc+\v\n\x8b\xdd!\xa6ӣ\xf9C\x13\xfb\xf9\x03\n\xf8=a\xbe\xb7\xed\xc5\xf5\xb55\xc4sq\xd1\xe9\xc9\xea\xd8\xe3\xc6\b\x17:\xfb\x86\xef\x1da\xff\xa7C\x9f\xafዮ\xe3m\xbe\xbb\xfa.8F}\xf6\xdcG\xe4\x1b\x04\xcfg:8\\\x15\xe5\nL\x83\xe7U\x89\xae7w\xef\xa1\xf0\x8c\xfb;\x8atg\x1a\xfbF\x8a{\xc7Y\xbf320~\xe9\r\xf1vO\xf3+d\xeciޒ\xefN\x84ϱBo\x900\xec\x95\xfaEQ7\x1b\x11\xe0\xa5S\xb2K\x1b\xd3@\xf0%\x10\x82\x95jNR\xaf\x80\xcf:\xa2<\xce\fe\x91\x86u\xc6\xcc\xe0O\xccg\xd4\xef\xdc\x01ŠHW)(\t\x8a\xe1\x1d\x1a\x9a\xfcG\xaae\xf4>]Q\xd9\xca/\x93\xe9\x86kEtT\x9e\xbf\x1e\xef\xdfP\xd2۽gzq\ve2\x1a\xe7\xb1\b\xaa\xe5\x17\x14\xaf\xb1\x96&\x8d;%#\x7f\xc7/\xbcc\xa2f+\x8aߜ\xca\x03\xf8\x06\xc4O;\xc7,\xf8h\xf2=?}æ\x80\x18\xf8\xb9\x05R\x98\x19\x8c\x15B\x8d\x1a\tk\xa8^\xf3\xcd\xf5\x1a\b\xfbS܍\xf5\xbd\xa0\x15\xf0\xfd_\x90\x9ai#\x13\xb5\x16\x95\xc6\x15\x90\x8f\xe7\xbal6q\u05c903\x86G9?\xb0\xcf\\c\xec\x86\xf1bg\xc0\xd9\xfb\xa5\x80/\xf82c}\xf0Vb\bx:Fg3\x99\x1d\x82\x13c\xe0GZ}\xc0\xd2\xf0\x97a\xb0\xfc\x1f\x00\x00\xff\xff\xc02\xee\xedJ\x0e\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4ZKs\x1b7\x12\xbe\xebWt)\x87$U\x1e2\xf6\xa6\xb6\xb6x\xb3\xe5͖v\x13Yeʾ\xa4r\x00\a=3\x88f\x00\x04\xc0\x90\xe2f\xf3߷\x1a\x0fr^$E:\xb1\xe7b\x13\x8f\xee\x0f\xfdFCY\x96]1->\xa2\xb1B\xc9\x050-\xf0ɡ\xa4_v\xf6\xf8\x0f;\x13j\xbe~y\xf5($_\xc0Mk\x9djޣU\xad\xc9\xf1-\x16B\n'\x94\xbcj\xd01\xce\x1c[\\\x010)\x95c4l\xe9'@\xae\xa43\xaa\xae\xd1d%\xca\xd9c\xbb\xc2U+j\x8e\xc6\x13O\xac\xd7\xdf\xcd^~?\xfb\xee\n@\xb2\x06\x17\xa0\x15_\xab\xbamp\xc5\xf2\xc7V\xdb\xd9\x1ak4j&ԕ\u0558\x13\xedҨV/`?\x11\xf6F\xbe\x01\xf3\xbd\xe2\x1f=\x997\x9e\x8c\x9f\xa9\x85u\xff\x99\x9a\xfdQX\xe7W\xe8\xba5\xac\x1e\x83\xf0\x93VȲ\xad\x99\x19M_\x01\xd8\\i\\\xc0\x1d\xc1\xd0,G~\x05\x10\x8f\xe8ae\xc08\xf7Bc\xf5\xbd\x11ҡ\xb9!\nIX\x19p\xb4\xb9\x11\xday\xa1\xdc+\x0e\x01 \x04\x84`\x1ds\xad\x05\xdb\xe6\x150\vw\xb8\x99\xdf\xca{\xa3J\x836\xc0\x03\xf8\xd5*y\xcf\\\xb5\x80YX>\xd3\x15\xb3\x18g\x83x\x97~\"\x0e\xb9-\x81\xb6\xce\bYN\xc1x\x10\r¦B\t\xae\x12\x16\xc2ia\xc3,\xc11Οr\x9a\xb1\x9f\xa7\xedֱF\xf7\x10\xdc\x18d\xfb\xad\x01\x02g\x0e\xa7\x00\xec\xe4\t\xaa\x00W!I\xde\x1b\x16\x13R\xc8\xd2\x0f\x05M\x80S\xb0B\x0f\x119\xb4z\x02\x99\xc6|\xa6\x15\x9f\xc9D\xb4\a\xebn0zJ6\xb4\xfe\xcfF\xd5\x03t\xaf\xf8\x05P\xce\xe2\x1b\x16\xf7\xb8~\xec\x0e\x9d\xb4\x8f\n\xfd\x9aļյb\x1c\r\xb1\xaf\x98\xe45\x92f\x198ä-\xd0\x1c\x80\x91\xb6=lu\x1ḟD\xaf3s\x8e0\xa2\xef,\x9d2\xacD\xf8Q\xe5>@\x91I\x1b\xecٴ\xadT[sX%.\x00\xd6)3i\xe0\x848\xec\x8at\x13ف\x9f\xf5y\x1eFߡ\x9d\xe2\xe9,'\x1f\x11JN{\xd0\xeb\x12\xa7\xbd'L\xaf_\x86p\x95WذE\\\xa94\xca\xd7\xf7\xb7\x1f\xff\xb6\xec\r\x03h\xa34\x1a'R\xf8\f_'9tF\xa1/\xea\xffe\xbd9\x00b\x10v\x01\xa7,\x816\xd8d\x18C\x1e1\x05\xf5\b\v\x06\xb5A\x8b2\xe4\r\x1af\x12\xd4\xeaW\xcc\xddl@z\x89\x86\xc8$E\xe5J\xae\xd180\x98\xabR\x8a\xff\xeeh[\xb2=bZ3\x87ց\x0f\xb5\x92հfu\x8b/\x80I>\xa0ܰ-\x18$\x9e\xd0\xca\x0e=\xbf\xc1\x0eq\xfc\xa4\f\x82\x90\x85Z@圶\x8b\xf9\xbc\x14.\xa5\xcc\\5M+\x85\xdb\xce}\xf6\x13\xab\xd6)c\xe7\x1c\xd7Xϭ(3f\xf2J8\xcc]kpδ\xc8\xfcA\xa4O\x9b\xb3\x86\x7feb\x92\xb5=\xb6#\xab\t\x9f\xcftg\xa8\x87r\x1f\b\v,\x92\nG\xdck!Ů\xf7\xff\\>@B\x124\x15\x94\xb2_:\x92K\xd2\x0fISȂb\x00\xed+\x8cj\xa98\x9e8ܝ\xe28\x05\x9b\xb6\x82\xabX\xb0n*\xde(\xb8\xb5R\x8e\xb9Ч\xe4Y\xc0\xb4\xe2'pE\x8e\f\f\x16hP昢\xe0\xb1\xcad\x02Y\xb7f\x18c\x8a\xfc'\xe5C_!\xb0\xe6>\x8b\x9e\xe6=i\xa2\xf4\xdd\x16\x01\x84\x8f\x8dN\x01\x03-0Ԟ\xbb\xbc\x04BZ\x87\x8c\xc7A\n\a\x06\xe3܋\x10\xf3\x0e\x82\xa4o\x9f\xbfH'\xc0(\x06\v\x0e\xff^\xbe\xbb\x9b\xffK\x85s\x00\xcbs\xb4\xbe\xc8vؠt/vu?G+\fr\xaa\xe2q\xd60)\n\xb4n\x16\xa9\xa1\xb1?\xbf\xfaeZ~\x00?(\x03\xf8\xc4\x1a]\xe3\v\x10A滰\x9e\xccF\xd8p\xf0\x1dE\xd8\bWy\xa0Z\xf1x\xc0\x8d?\x82c\x8f\b*\x1e\xa1E\xa8\xc5\xe3\x84\xff\x84\xef\xdaWM{\x98\xbf\x93\xf7\xfcq\r\xdf\x047\xbe\xa6\x9f\xd7\x01\xc6.\x81w\x1dl\x0f'x\x99\x11e\x89\xfb\xf2ld,\x94p(T\x7f\v\xca\xd0Y\xa5\xea\x90\xf0\x84IO!R\"\x1f\xc1\xfb\xf9\xd5/\xd7\xf0M_\x06\aX\t\xc9\xf1\t^\x81\x88w$\xad\xf8\xb73x\xf0v\xb0\x95\x8e=\x11\xa7\xbcR\x16%(YoCi\xbcF\xb0\x8a\xeeVX\xd7Y(\x958l\xd8\x16Tq\x80OR\x11\x99&\x03͌;Z.\xa5\xef\xe1\xdd\xdbw\x8b\x80\x8cL\xa7\xf4Q\x972j!\xa8(b\x92\xc7<\xed\xed\x8e@\xb7\xc1$\x9c\x82\xbcb\xb2\xc4p2\x84\xa2\xa5)\xb8|\xb8}\xfb%=\xaa\x15\x97D\x92\x03\xb7\x86\xf0=e{TY\xc3t\x16V3\xa7\x1a\x91\x0fVS\xd5|\xcbII\x85@s\xa2\xcc|\xdf[\x9c\n\xe1\x89\xfa{\xb7\xe6\xac:ױr\xa2\xb0\xec\xf6M\x8f\x95\x9fG\xe5u\xda\x14\x1eXi\x81\x19\x04\x06\r\xd3d\x11\x8f\xb8\xcdBe\xa3\x99\xa0\xb2\x84*\x8f]\x9f\b\x98\xd65\xd5\x0e\xa1Z\x99\xa0\x18\xeb\xec(\x1ef\xfd\xf9\x0e\tdR\x95\xa9/\xb6DGw\xf3/'\x9c\x0f\x03 \x7f\xae\xa0v]\xc3\\\xc9B\x94\xad\xf1w\xbe\xb1\xa4d[\xd7lU\xe3\x02\x9ciDŽ\x9e!\xc8\aZr\xfc\xfc\x1f:K\x93\x85\x9fhqN\x9f\xaa\xd7\xf8\x1c\x1f\x06eی\xa1d\xf0\xa8\xb4`\x13\xe3\x06\xad\x1by/M\\_\x9f\xe3c\xc1(/\xb9\xc3\xc7爉\xdbo4\xf4xQH7\xe0n\azR\xe9g\xc4\x06\x83\xbf\xb5t\xed\xe9\xe3Φ\x1b\x14\x835t7\x1f\fi\xc5\a#\xfd08\x98\xecuɻH\xc7]\x1b\xff\xf8qF\xdf&<\xeaD\x99\x86\xe4\xe8\xd2S\x0f\x95\xf7\x97vnrE\u05fc^\a\xf9\x12\x9dߌ\xc9\xf8\x8e\xab\xe1\xd11DCq\xa0\xf3.\x14\x19O\xb5^\xba\xe4\xc2N_\xa3\x105\xe4\xfe\xbaF\xb7ɂ\x89\x1a9\xa4ǿ3\xa9\xac\xb0\xa0\x1c\x1d\x9c45<\"\xbc\xc3\x17\xa5\x87\n\xc1\xfa\xfe\xe5\xd7vG\xb3\xb5\xc8}\xfblB\b\xe3\x8c](\xd30\x17Z\xf1\x19\x91\xb8,zM\xfal\x83ֲ\xf2\x94\xd3\xfe\x14V\x85>P\xdc\x02l\xa5Z\xb7k\x04\xf52\xd2\xd76\x1a\xday\xbd\xa8\xc9\x16K\xdfƙ\xab\x92I\x17m]\xfb=\xdd\xe8\xb0\x7f\x18\xf6\xa8V8]\xd7\x1diD\x1d\x03X1{JT\xf7\xb4f\xca\xebv!\xed\xa8\xdb\xc1\x91\xf0}\x87\x9b\x89\xd1\xd1Kmw\xf2&\xb9\xcc\xc4\xdc\x0f\xde\x1b\xce:\x7fdt\x89\xbb'\x90P\xa9:y\xb8r\xac\x06\xd96+4$\x9c\xd5֡\x1d\x04\xfe\xd0D\xd8Ir\xea\xf6\xb7ߟ\x94\x1a(\xc5NIΤo\xf1\xdbP&pauͶ\xbb\xb3\xf8\x9a\x9b\xfck\xba\x15\xbc7\xf2\xe4\xe9\x1a\x0f\xd5\x10\xc7[\x98\x1e\xd3[%\x0f\xdcR\x93\x93\v\xe9\xfe\xfe\xfd\x91\xa2]H\x87\xe5 \x8d\xc4y\x12\xe7\x1b\xe2\xf2\xd7p8R\x03Yɴ\xad\x94\xbb}{\xc24\x96\xbb\x85\xc9E\xf6\xf5\xbc\x0f\x88\xfe\x95!.\x8a\xa60\x01u\x1fp\xce\xf2\xdf\xfe\x1f\x0e\\b\xc5\xcb\x1e\x85\x13\xf9*\xfe\x1d\xc3TVX\xa2f\x86b\x82\x7fú\x19\xbeȾ\x00+|\xa3\x9d\xaa\xddP\xfe\x86\x86\xd9\xd4uNI_\xc0)3~P\x84\x93\t\xa8\x7f\xa0ϙ{&\xcdi4\xe8\x91\xf3\x0e\xed\xf8|\xd3\x1diW\xbb\x97\xcd\x05\xfc\xfe\xc7\xd5\xff\x03\x00\x00\xff\xff\x8b\xcb\x17\x16\x81$\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4Y_s\xdb6\x12\x7f\xf7\xa7\xd8q\x1f\xda΄R\x93\xeb\xdc\xdc\xe8-q\xae7\xbek\x1dO\xe4\xe4\xa5Ӈ\x15\xb1\"Q\x93\x00\n\x80\x92u\xbd~\xf7\x9b\x05H\x8a\xff$YJ\x9b\xe0\xc5\x16\xb0X\xfc\xb0\xff\xb1L\x92\xe4\n\x8d\xfcH\xd6I\xad\x16\x80Fғ'ſ\xdc\xec\xf1\x1fn&\xf5|\xf3\xf2\xeaQ*\xb1\x80\x9b\xcay]\xbe'\xa7+\x9b\xd2[ZK%\xbd\xd4\xea\xaa$\x8f\x02=.\xae\x00P)푧\x1d\xff\x04H\xb5\xf2V\x17\x05\xd9$#5{\xacV\xb4\xaad!\xc8\x06\xe6\xcdћ\xeff/\xbf\x9f}w\x05\xa0\xb0\xa4\x05\x18-6\xba\xa8J\xb2伶\xe4f\x1b*\xc8\xea\x99\xd4W\xceP\xca\xcc3\xab+\xb3\x80\xfdB\xdc\\\x1f\x1cA\xdfk\xf11\xf0y\x1f\xf9\x84\xa5B:\xff\x9f\xc9\xe5\x1f\xa5\xf3\x81\xc4\x14\x95\xc5b\x02GXuReU\x81v\xbc~\x05\xe0Rmh\x01w\f\xc5`J\xe2\n\xa0\xbeg\x80\x96\x00\n\x11$\x87Ž\x95ʓ\xbda\x16\x8d\xc4\x12\x10\xe4R+\x8d\x0f\x92i\xf9\x80^\x83ω\x8f\fRE\xa9\xa4\xca\xc2T\x84\x00^Ê\xa0F\"\x023\x80_\x9dV\xf7\xe8\xf3\x05\xccXp3\xa3\xc5L5?\x81>N\xc4\xe5\xcd\xcb\x18\xcaҜJ\\Ԕڐz}\x7f\xfb\xf1o\xcb\xde4\x80\xb1ڐ\xf5\xb2\x89\xaeqt\x92Gg\x16\xfa\x92\xfd_\xd2[\x03\xe0\x03\xe2.\x10\x9cE\xc8E'\x89s$jL\xd1y\xa4\x03Kƒ#\x15\xf3\nO\xa3\x02\xbd\xfa\x95R?\x1b\xb0^\x92e6\xe0r]\x15!\"m\xc8z\xb0\x94\xeaL\xc9\xff\xb6\xbc\x1d\xfb\"\x1fZ\xa0'烬\xad\xc2\x026XT\xf4\x02P\x89\x01\xe7\x12w`\x89τJu\xf8\x85\rn\x88\xe3'\xb6\x1f\xa9\xd6z\x01\xb9\xf7\xc6-\xe6\xf3L\xfa&\xa5\xa6\xba,+%\xfdn\x1e\xb2\xa3\\U^[7\x17\xb4\xa1b\xeed\x96\xa0Ms\xe9)\xf5\x95\xa59\x1a\x99\x84\x8b\xa8\x90Vg\xa5\xf8\xca\xd6I\xd8\xf5\x8e\x1dyd\x1c!\x11\x9e\xa1\x1eΌ \x1d`\xcd*^q\xaf\x85&\xbe\xbf\xff\xe7\xf2\x01\x1a$QSQ){ґ\\\x1a\xfd\xb04\xa5Zs\x84\xe6}k\xab\xcb\xc0\x93\x940Z*\x1f~\xa4\x85$\xe5\xc1U\xabRz6\x83\xdf*r\x9eU7d{\x13\xca\x0e\x0e\xae\x95a3\x17C\x82[\x057XRq\x83\x8e>\xb3\xaeX+.a%Vf\xe9\xb5Ō~ԑ\xe7\x90\xe8\x94\xd9\xf1x3ŨA\xac:\t5\x9e\b.RBQ\x93N\xb0\xdc\xe6d\xa9\xbbǒ\xd1Nzmw\xcc8\xa6\xe2\xa1I\x1c\xd4N\x90\x83\x16'\xeeƹ$8\x90\xa55YR)5\xe1\xe6X\x994\x01\xbeS-\x8c!\x1e\xd6\a\x1c\t͓\x80_\xdf\xdf6᷑p\r}\x14aO\x8a\x87\xc7ZR!B\xb6:}\xf6\xa4!\xf0\xb8]G\x10!\x06y\r\bFR,\x83\xdb\xf8\x0fR9O(\xeaIv;K\xf5ڋ\x18[\x0e\x82\xe4\xb1\xcf\x13\xac\x12@\x8euR\xc0\xbf\x97\xef\xee\xe6\xff\xd2\xf1\x1e\x80iJ΅r\x80JR\xfeE[\x12\brҒຈf%*\xb9&\xe7g57\xb2\xee\xe7W\xbfL\xcb\x0f\xe0\am\x81\x9e\xb04\x05\xbd\x00\x19eކ\xcf\xc6j\xa4\x8b\x17o9\xc2V\xfa<\x005Z\xd4\x17܆+x|$\xd0\xf5\x15*\x82B>Ҵ\xf4\x01\xaeC\xa1\xb9\x87\xf9;\xbb\xd6\x1f\xd7\xf0Mt\x96k\xfey\x1da\xb4\x89\xb2\xeb}{8>G\x0f\xde\xca,\xa3}E;2\x16\x0e\xec\x1c\x12\xbf\x05m\xf9\xaeJwX\x04Ƭ\xa7\x18\x90H\x8c\xe0\xfd\xfc\xea\x97k\xf8\xa6/\x83\x03GI%\xe8\t^\x81TQ6F\x8bog\xf0\x10\xec`\xa7<>\xf1Ii\xae\x1d)Ъ\xd8\xc5\a\u0086\xc0\xe9\x92`KE\x91ĒD\xc0\x16w\xa0\xd7\a\xceiTĦ\x89`\xd0\xfa\xa3eI3\x1e\u07bd}\xb7\x88\xc8\xd8t\xb2\x10\xdb8s\xad%\x17\x1f\xa8D\x9d\x0f\x83\xdd1\xe8*\x9a\x84א\xe6\xa82\x8a7#XW\x9co.r\xceq=Ќ\xe7\xf9e\xa8\x0f\x9e\x15%\xbeXn}\xa6$B!\xfc\t\x92\xe8>\xf1.\x90\xc4c\xb5\"\xab\xc8S\x10\x86Щc9\xa4d\xbc\x9b\xeb\rٍ\xa4\xed|\xab\xed\xa3TY\xc2F\x9fD\xebr\xf3\xf0~\x9f\x7f\x15\xfe\\z\xf1\xf0\xd2\xff\xd4\xdb\xf7\x1a\x13\x9f_\x04|\xba\x9b_\"\x81\xa6n}~\x8e<(\x87e]I\ry\xb2\xd3ns\x99\xe6\xcd+\xa6\x13\xd5K\x141\xec\xa3\xda}!\xdfa9W\x96\x11풺I\x97\xa0\x12\xfc\xbf\x93\xce\xf3\xfc%\x82\xad\xe4'\x05\x97\x0f\xb7o\xbf\xa4GU\xf2\x92Hr\xa0:\x8f\xe3)٣JJ4I\xa4F\xafK\x99\x0e\xa8\xb96\xbd\x15\xac\xa4\xb5${\xa2\xca|\xdf#n\xaa\xe4\x89*\xb7\xa59\xab\xccu\n\x8d˵\xbf}{\x02Dz%l0\xecuX\x17\xb7\r\xafA\a\xec<<\xc1\xb7\xee\x0eG\xae>\xa8>u\x83L[\x99\x85Tۆ\x8f\xf0\xf4QXb\xb7\xf3\xd9\x1d%\x1a#Uv\x16֦\x91\xb8$\xcf\xcf\xe5\x89\x02\xbd\xdb\x02>V\xc6\x1f\xb5\xbb\xd3.\xf5a\x00\x04\xd0\x12 ߉5\xf4H\xbb$V\x8b\x06%\x97z\\\xcd\xd5%\xf1\x8a\x00\x8d)\xb8\x1e\x8b\x15\xe0\x94\xaf7m\xd1T\xab\xb5\xcc*\x1b\x1eacI\xa9\xaa(pU\xd0\x02\xbc\xadƌ\x8e\xb8O\xb7#{B\xe3\x1f:\xa4\x8d\xbaO\xf4\x84\xa7o\xd5\xeb\x14\x8f/C\xaa*\xc7P\x12x\xd4F\xe2\xc4<\x1b\xfb\xc8\xd1y\xe1\xfa\xfa\x1c\x93\x8a\x9etB\x06u\x03s\xe2\xc1\\;b\xfd|\xe0\x19~\xa4\x06w\x9cΎ\xe7:\xa8\xa5\xdf*~\v\xf5\x11&ӽ\x81\x01\x8d\xd1\xe2j(\xb4nl\x1b,\xee#\xd3p\xa1\xef\xf4\x83\xd5^c\xbd{\x9bq[%tm\xcfi\xac\xc4Nq-\xf7\x98V}\xd3?\xe6\x87\xc1ŭ\x95T\xf3\v\xb1\xd7佤\xb1r3f\x13\x9a\xa2VԎ\"K\n\xfd\x8a\xd8\xf9ޢkN\x9e2\x82.\xbf\xb85\xd47̎Dx\xea\xf1Kt\x8d\xb2 \x01\xed\a\xbc\t6\x0f9\x81\v-\xc1\xaf]˨r$BT\x9e\x00=N\xceM\x03^\xa0\xa7\x84Y\\\x16}&}\xae$\xe70;\xe5t?E\xaa\xd8\xf1\xa9\xb7\x00\xaet\xe5ۖO\xed}\xb5(\xbev\xb5i\x9c\xd7v\xcaѝ\x82r\xcf4Sf\xd8Ɓ\xe3v\bG\xe2\xdb\x1dm'fG\x1fD\xba\x8b7\x8d\tM\xac\xfd\x10\xac\xe3,\x01\xd4\a]b\xff\rH\xc8uј\xbc\xf6\\\aT\xe5\x8a,K'|\x9ai\xc4\xd4\x16,\xf1I\xde\ns\xea-\xd5rh\xa2fdU\xb7\x1dRT\xa1/\xedb\"\x15ҙ\x02w\xedeB\x01\xcb\x16<ݽܛQ\xe3\x9a\x1c(\x0e\xa4\xd9\xe3\r\xc1\xf6\xd3\xd3ty>\xf5!\xab?\xc6_\xa5\x06\xeb\xed7\xb7\xbf\xe6\x84#e\x82\xf3h\xfd'\x05\xc8e\x8fé\xd8\x18Λ\x8e\x8c\xc7CZ\xff\x98\xcf\x19\xcd&\xa57\x9a\f\xc8E\x87w\xdda\xef\xceT\xab\xf6\xf3\xd3\x02~\xff\xe3\xea\xff\x01\x00\x00\xff\xff\xc5p\x17\xe3F\"\x00\x00"), - []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xdc=]s۸v\xef\xf9\x15\x98\xf4a\xdb\x19˹\x99އ\x8e\xdf\\\xafӸ\xf7\xae\xe3\xb1\xd3\xec3D\x1e\x89\xb8\x06\x01.\x00JѶ\xfd\xef\x1d\x1c|\x90\x94@\x12\x92-o\xb6xɘ\x02\x0e\x80\xf3}\x0e\x0e\x90\xc5b\xf1\x8e6\xec\x1b(ͤ\xb8\"\xb4a\xf0݀\xb0\x7f\xe9\xcb\xe7\x7fӗL~\xd8||\xf7\xccDyEnZmd\xfd\bZ\xb6\xaa\x80\x9fa\xc5\x043L\x8aw5\x18ZRC\xaf\xde\x11B\x85\x90\x86\xda\xcf\xda\xfeIH!\x85Q\x92sP\x8b5\x88\xcb\xe7v\t˖\xf1\x12\x14\x02\x0fSo\xfer\xf9\xf1\xaf\x97\x7fyG\x88\xa05\\\x11\x05\xdaH\x05\xfar\x03\x1c\x94\xbcd\xf2\x9dn\xa0\xb00\xd7J\xb6\xcd\x15\xe9~pc\xfc|n\xad\x8fn8~\xe1L\x9b\xbf\xf5\xbf\xfe\x9di\x83\xbf4\xbcU\x94w\x93\xe1G\xcdĺ\xe5T\xc5\xcf\xef\bхl\xe0\x8a\xdc\xdbi\x1aZ@\xf9\x8e\x10\xbft\x9cv\xe1W\xbd\xf9\xe8@\x14\x15\xd4ԭ\x87\x10ـ\xb8~\xb8\xfb\xf6\xafO\x83τ\x94\xa0\v\xc5\x1a\x83\b\xf8\x9fE\xfcN\xc2B\tӄ\x92o\xb8Q\xbb\x1aD<1\x155DA\xa3@\x830\x9a\x98\n\bm\x1a\xce\n\xc4;\x91\xab\x1e\xa40J\x93\x95\x92u\amI\x8b\xe7\xb6!F\x12J\fUk0\xe4o\xed\x12\x94\x00\x03\x9a\x14\xbc\xd5\x06\xd4e\x04\xd4(ـ2,`ٵ\x1e\xef\xf4\xbeNm\xcc6\x8b\v7\x8a\x94\x96\x89\xc0m\xc1\xe3\x13J\x8f>\"W\xc4TLw[\r\xdb#T\x10\xb9\xfc\a\x14\xe6r\x0f\xf4\x13(\v\x86\xe8J\xb6\xbc\xb4\xbc\xb7\x01e\x91Uȵ`\xbfG\xd8\xdan\xdcNʩ\x01m\b\x13\x06\x94\xa0\x9cl(o\xe1\x82PQ\xeeA\xae\xe9\x8e(\xb0s\x92V\xf4\xe0\xe1\x00\xbd\xbf\x8e_\x90xb%\xafHeL\xa3\xaf>|X3\x13$\xaa\x90u\xdd\nfv\x1fP8ز5R\xe9\x0f%l\x80\x7f\xd0l\xbd\xa0\xaa\xa8\x98\x81´\n>І-p#\x02\xa5\xea\xb2.\xff)\x12u0\xad\xd9Y\x1e\xd5F1\xb1\xee\xfd\x80\x02q\x04y\xac\xa88\xc6s\xa0\xdc\x16;*\xd8O\x16u\x8f\xb7O_\xfbLɴ'J\x8f7\xc7\xe8c\xb1\xc9\xc4\n\x94\x1b\x87\xacia\x82(\x1bɄ\xc1?\n\xce@\x18\xa2\xdbe͌e\x83\xdfZЖ\xdf\xe5>\xd8\x1b\xd4:d\t\xa4mJj\xa0\xdc\xefp'\xc8\r\xad\x81\xdfP\roL+K\x15\xbd\xb0DȢV_\x97\xeewv\xe8\xed\xfd\x104\xe2\bi\xbd\x16yj\xa0\x18H\x9a\x1d\xc6VA]\xac\xa4\x1a(\x19;d\x88\xa3\xb4\xf0\xdb洈U\x8b\xfb\xbf\xccq\x99m\xff\x1eG[~\xb3+k\x05\xfb\xad\x05T\xa6N\xfc\xe1P_\xa9\x9ej\x1f6\xcbF\xfb\xd4\x1dE\xb4m\xf0\xbd\xe0m\te\xd4\xeb\a\x1b\xcc\xd9\xc6\xed\x01\x144z\x94\t+D\xd6\xfaؽ\x88\xeeWT\xe0T\x01\x11\xd2$\xe01\xe1\xe0\x11&\x10\x03I\x9a`G\x03ubœ[&D\xb4\x9c\xd3%\x87+bT{\x88F7\x96*Ew#\xd8\n\x1e\xc0\x8b\x90\x15\x81xU\xc3Y\x81$\x8f\n\x05\xf1\xf5\xe7E\x15\xd3VQ\x86]>HΊ\xdd\f\xben\x93\x83\x82\xb4z\xd9\xf5;$K\xa8\xe8\x86I\x95\x12\x03\xa9\xb0kϞwjZZ-\xe9\x81\xec۸\xcc\r'\x91UI\xf9<\xc7\x10\x9fm\x9f\xce:\x90\x02\x1dʸ\x15Omo\xbb\x97@\xe0;\x14\xadI,\x93\x90\xb2E\xd3$\x15i\xa46\xe3t\x1fW]\xa4\xef\x1c\xa5~\x9c`\x9a\x83\x9d%Y\xdd5\xaf\x84\x03Q-\x0e\x06\nY\n\xb0ۨ-Q\xbb\xbeJ\xb6\xae\xef(RȒj(\x89\x14\xa33#\xbb\xb4\x1c\xb4\x9f\xabD\xce\xe8\xf4\xd0E\xb7\x7f\xf4x\b\xa7K\xe0D\x03\x87\xc2Hu\x88\xcc\x1c\x94\xba\x96\xa3XGP\x99ЦC\t\xe860\x01\x92XN\xdfV\xac\xa8\x9c\x87a\xd9\x13\xe1\x90R\x82\xb6\xda\x04]\xe6\xdd\xd8&\xc9\x1c\xf9\xfd$Sڣk3b\xb5\x0f/\xa5Q\xba\x96\xa1\x86\xbb\x96Dm\xa7{\x0ft\x8b\xffn\xe4\xe4\xb6\xff\x7f\"6\x18\x93\x13\x98vB\xfe\t\xba\x9f\xd9<=ʷ\x18ၾ$w+\x02ucv\x17\x84\x99\xf0uN\x12(\xe7\xbd9\xfeĴ9\x9e\xe93I\x93#\x13g\"L\x9c\xe2OH\x174\x19O\xdebd\xd3\xe4\xef\xfdQ\x17\x84\xad\"\xd2\xcb\v\xb2b܀\xda\xc3\xfeI\xaa>P\xe65\x90\x91c\xf5\b\xe6\tLQ\xdd~\xb7.\x8e\xee\x92`\x99x\xd9\x1f\xec|\xe3\x10A\f\xcd\xf3\f\\\x82\xf12SPc\x1cN\xbe\"6\xbb/\xe8T_\xdf\xff|\x18+\xef\xb7\f\xce;\xd8Ȍйv\xbd\xb7\xa3\xfe\xfa|T\x10~A\x1f(\x06U.\xe7rA(y\x86\x9ds]\xa8 \x96>4tΘ^\x01&\x7f\x90Ϟa\x87`\xd2ٜÖ\xcb\r\xae=C\xc2\xf5O\xb5\x01\x0e\xed\x9a|X\xec\xf0d? \"0\x86\xcfe\x03\u05fc($r'閩KB\v\xb8?a\x9bY\xacҟ\xa3\x9f\xfaD\x0e\xf8I;ZZ\x89\xa9\x98\xcfij@\x99\xc9%\xa8k\xdf(ge\x9c\xc8\xc9ȝ\xb8 \xf7\xd2\xd8\x7f0@\xd3\xc8(?K\xd0\xf7\xd2\xe0\x97\xb3`\xd4-\xfc\x9c\xf8t3\xa0\xa0\t\xa7\xe5-\xc2\xfa9?g\xd3,\xb7E\xdc3M\ue10dW\x1cJ2\xa7\xc2\xf4\xae\x9b\xceMT\xb7\x1a\xd3uB\x8a\x05\xda\xcc\xe4L\x1e\xdfR\r\xd0\xfd\xe2I\xfd\x84_\xad\xb1p\xbf\xb8$3\xa7\x05\x94!\xb2\xc4\xec'5\xb0fE\xe6|5\xa85\x90ƪ\xf0<\x8e\xc8T\xac~7DZO\x9e\xf5\xee\xb7\xef\x8b\xe7\x98/XX\x93\xb3\xf0\x10\x8c\xac3p\xe0uw9\xbf\x9f\x85\x95ٌ^\x81\x13f\xbb\x8e$Gǻ\xe6 \xe5\x05\xe8@+\x8e.\xce,uiY\xe2\x11\x1a\xe5\x0fGX\x94#x\xe1X\xd5\xd0[\xbb3\xc15m\xacZ\xf8okiQ\x9a\xfe\x974\x94)}I\xae\xf1\xa4\x8c\xc3\xe07\x9f\x87\xeb\x81ɘ\xb2\xb1SY\xfe\xd9Pnm\xbfU\xe0\x82\x00w\x9e\x80\\\x1d\xf8E\x17d[I\xed\xcc\xf6\x8a\x01\xc7\xf3\x8a\xf7ϰ{\x7fa\xa7\x9f\x9d\xb2\xafd\xde߉\xf7·8P\x18\xd1ᐂ\xef\xc8{\xfc\xed\xfdK\\\xa9LN\xcd\xec6`њ6y\x1c*\x92\xc9\xfa\xae\r8\xa6\x9f\x9b\xef\x92\xf2\xdeɞ\xdam\x16\x8b6R\x9b\xcf\xe9\xbc\xe1\xc8z\x1e\u0088\xa1g\x9cȱ\xcdF\f>\x8f\x16\xf5\xbdu\"W\x06\x94\xcf%:\x1b\x10\xe2\x8f\x17Ff\xa9S\x99\xfebc2\x90\xc6\xfc\xaeE\xf0\f7\xb9\x83\x9b\x9c%\x1e\xe3\xb0Z\xbc\x1c\xe9\xed\xdf~\xef\xe53\xad\xe4ڿ\xfb\x1bym\x87\xba\x90uM\xf7O5\xb3\x96z\xe3F\x06\x9e\xf6\x80\x1c\xf5պEyε\xc8\x1d\x0f\xe1\xf9喙\x8a\tB\x83\xda\x00\xe5\x19\x8a\x92F\xa6rةVQM\x96\x00\"\xa6\xe8\x7f\x04W\xa2f\xe2\x0e' \x1f\xcf\xe0zDt\x9d\xd3ٽ\x894\x89\x94\x8f\x1f\x9c\xc9jdI\xb6\x15(\x180\xc6a\xde\x1d=U!M/eq\x84C\xda\xc8\xf2'MVLi\xd3_\x82&\xadΥ\xf5\x91\xe4\xb3\xeb\xfe\xcaj\x90\xad9'\x82o\xbbi\x06g\xcd5\xfd\xce\xea\xb6&\xb4\x96\xad3\xe6\x86\xd5\xf1TףwK\x99\x89\xc7V\x98\xbf1Ғ\xa0\xe1`\x80,a\x95>\xefM\xb5B\n\xcdJP\xa1J\xc1\x91\x8dI+\x98+\xcax\x9b:%J\xb5c#`q\xab\xd4I\x01\xf0\x177\xb2\x97w\xac\xe4v\x88\xa0̽\xe3A\x1a\x10\xb6\"\xcc\x10\x10\x85\xc58(\xa7\x92q\n\x8f\fD\r\xcb\xd5sy\n\xdc6\x10m\x9d\x87\x80\x05\n$\x13\x93)\xb7~\xf7O\x94\xf1s\x90\xcdr\xde'\xa9\x1e\x81\x96\xa7\xe4h~\xed\r' t\xab\xf0\xf0\xdf\xe9\x8e-\xe3yk\xb6\x94#\x9c\xb6\xa2\xa8\x00\x95\x90\x18\xea\x06\a\x9e\tm\x80\xe6\xf2\x82\xf5\x8aZ!\x98X\xe7\xd1.;\x11\xda5\x87\ua954\x1c\xe8\xf8)d\xd7,\xae\xdf@\x13\xfd\xdaM\xf3BM\xd4\x11\xc1\x1d\x9b#\x1d\xb2)j\x95\x16\xa1\xc6@\xdd8\x91\x93D\xb5\xa2o]Π\x88\x8e\t\xc3\xfd*^3\xbef\x82e\xd0v@\xd7;\xc1L\xdfy\xb4 \xce\xea<\xda\t\xa2;pJ\x86\xedn\x00\xc0\nh\x88Cp\xed\x91k\x8ep$\x97@hYB\xe9r\x97\xd6\x15\xf1a\x89+|\x1b)nH\xee\xeexO0\x8b\xb2\xa1\r\x82N\xccê\r,Z\xf1,\xe4V,0\x18\xd7G\xeb\x90\x13\xb3T/\x9dޜ\xac\x8c\xe6\xf5K\xbe\x9a\x9e\xd3BC~\xcd\xe7\xa9\xe0?\x9dA\xcbd\xf3\xcdQ\t\x8f).\x98\xd3k\xae\x00{\xe4\xc7\xd9UL\xcd?1\xd8\x1fJ߸b\xe9\x17\x95\xc5ݥA\xf5\x9c\xc2m\x05\xa6\x02\x15J\xb3\x17X\x92^N\x9e\x90v\xc1K\xac\x93\xb3L\x15\\dW\xfe\xb9W9\x87\xd1M\xcb\xf9\x85\xe5m\xda\xf2d8l$\x8a\xd8!geՏ\xa5=\x86\x9c\xea\x8bl<\xf6+-\x86\xf5\x85\xb1\n\"\x14\x18\xca0\xb3\xa7qj\xbfXX\xda;\xdf\x1f\x96S`\xfe/,\xff\x0f/=̨\x94\xc8Gcn\x95fDb\x02V\x82\xc1zh\xec\xea+|?_\xe8\xfbc\xe1\xd4@\xfd\xa5\xf1\x123\xea\xc2f\xa05\x01g\xaf\xde\x04\xadA\xab\x9d+\x10\xed\x80\xcf\x19\xda\xf1ׅ\xbb\x05\x11\xc0\xa4\xf8\xf5k\x05A|}\xf5>\xd3䯤\x92m\xa2\xaao\x02e3\xd5\x1d\xf3\x1b\x1e\x14z\xf8\x03\x050t\xf3\xf1r\xf8\x8b\x91\xbe\xec\x03\xb3h\t@\x18\x14u\x99Y&J\xb6aeKy\x90\xda\xee\x0e\x81c\xa0\x8e\xcf\x12Ф\"\x82qǀa\xfc\x80\xe1ȗ\xc6\x1d\xcb\x1c\xad\xe2\xa6}ѼꐓkB\x865\x1f#\xd6\xf0\xd8\xe3\x8bW\xa9\x82\xfdCj=\x8e\xaf\xf0ȉ$f\xaa9N\xa8\xe1\xc8,\x16{\xf1yKN\x95\xc611\xf7\xd9*2^\xbf\x0e#\v?\xf35\x17\xc7`\xe7\xec\xf5\x15oXU\xf16\xb5\x14\x99\x15\x14\xafW\n\x99\x17}\x9eT\n0\x1f\xb0\x8cWA\xcc\xd6>\xbc(\xa09iK\xb35\r\xc7T2\xccR'O\xccެV\xe1\xcd*\x14\u07b6.a\x92\x8b&\x7f<\xa6\xf2 \xc6I\xbfЦab}\xc8\x14\xb9\xac3\xc96\xf3,s\xbf\xb7\x90\x01\xcf\xf4Ù.:\x1c\t}\xddu\xe9D$\x19ҖL\x18yI\xae\xc5\xce\xc3M\xc0酏B\x9a\x83\x8blvY[\xc6y\xff\xb6\x16\x82\x9d\x06\xe5\xefLjZ\xbbU\x8dy\xfbI\xbaJ5p\xcaO\n\x1c\xbf\xec\xc1\xe8gG\xdf\xd2\xf3\xaf[nX\xc3\xc1zt\x1bV&\uf419\nv\x11\xc9\xff\x90xCj\xb9CH_\x1e\xa3,^\xee\x051T\x93-pNh\x8a;\x0e\xb6_\xb8\x9bɅ\\\xe0\x95@K\xde\xc0$\xfe>\xf3\x85\x93b\xbc\x06\x86ԫ\x13p\v*\xf0v\xb3Nld\xd4\x1c\xe6h\xd1\x03\xbf\xdcE\x17\xf8\xed\xb7\x16Ԏ\xc8\r\x960xﭻ\xab\xe0Ս\xb61fP\x80^\x19\x8f\x1d*\x1c\x842\x9d\x82\"\xd7\xc2\xf9\x12\xfb\xeb\xc11V\xf3u\xa1\x9aU\xe76\nK\xce12\\\xc88:1l\xce\xed\xcf-\xea?o\xe0v|\xe86\xeb+\xe5\xfb\xb3\x7fP\xb1\xfe)E\xfay\xc7A\xb3E\xf9\xe7\n\xe4\xe6B\xb9l\xef5\xaf\xe8\xfe\xb8C\xd43\x16ٟ\xa3\xb8>\x13S9\xc5\xf4\xc7\xe1\xe9\r\x8a\xe7ߴh\xfe\xad\x8a峋\xe4\xb3\xce1\xb3\x0f\xadr\x8f\x19O\xac\xfa\x9e?u\x9f.z\xcf(v\xcf8I\x9b\xdf\xe4\t\xdb\xcb(f?\xae\x88=\x83f\xb9\xa2\xf8\x86\xc5\xeaoX\xa4\xfe\xd6\xc5\xe93\x9c5\xf3\xf3qE\xe8'\x9f\xc0\x84\xa3\xfe{Y\u0083Tf.8y\xd8\xef\x9f8I\xed\x05l\x92\x97D\x84\xae\x89]b\x88\xe1Ë\xd36\x95>\xf4\f\xee\xf4/\xb2\xb4k\x9b;cy\xdc\xeb~pWy\x05\n\x84{\xe6\xe3?\x9f\xbe\xdcG\xf8)\x9f\xd7{\xc6{\xcfK8\x0f\xa6\xf4\xc8\xf1Gs\xbe\x98\xc9a\v}\x80W>\x17\xa1\r\xfb\x0f|\xd5\xed\x05\xe9\xa0\xeb\x87;\x84\x11\xfc4|&.VQ\xc4\x13\xcb%X\x8b\x15Q5*\x16w\xab\x01\xc4a\xc5o\xff\x19%(ݓY\xc1b\xb2P\xe3e\x05\xef\xe1έcl\x96O\xd6i\x14;\"\x1dGVL\x95\x8b\x86*\xb3C\xb6\xd1\x17\x835\x0433\x95\xce\x19U\xac\x87π%\xd1\x1b^\xff³\xc8]3<\xed\xdd\xc7\xdd)\xeb\x18\xbf\x7f2{\xf3\xe4\x15\xd71n\xb1\x17\x88\xa9\xc4\xe7d\x81ɫ\xa5ɼ&z\xf8vR\xda\xe51\x8e\x9e\xd6s6\x8a\x0e\xa9\xa6\x04\x18;\x1eU\x9d\x16\xb4\xd1U\xe2ɥ\x97\xe9:|\x8d\xccPӾd\x93\x0e\xc0`\x9f\xac\xa8z\xdaj\vA\x9f\x85m\xa3\xb4Ⱄn\xb7\xb6\xd9ս0~\xd1\xcb\x14\xbc͑p\xe6s.'?\xe4\xe2\xd03\xa2~0\xfbeU\xdb!\xa6N8\f\x9eu\xed2\x8a\x8c\xa7\x9d\xd8\xccg@\xf2\f\xc6\tO\x7f \xberqE\x92/\x82d\xbe\xfa\xf1\x87\"zB\xab颂\xb2\xe5p\xea\x9b\x7fO\xbd\xf1\xf3\xaf\xfe\x85\xd92\xde\xfd\xb3\xc8\xee\x19h\xeb3\x0f\xdf\x17\xf4\x94\xf0\x90\xfb\x94\x1cs\xf808pϋ\x15\xee%ʢ\x00\xadW-\x0fUJ\x85\x02j\xa0\fݙ\x8e+>\xaaΦm\xb8\xa4%\xa8\x1b)V,qB2@\xeb\x7f\r:\xef\xf1l\x81\x1f[\xd5=\xed8\xf9,ދ4WC\x15\xe5\x1c\xf8'\xc6A\xff,\xb7®+C \x1fR\xe3z\xf7\xb2\x8aVY\xb3\xbe#\xa2\xad\x97\xd6\xc9\x05cƃŕT\xd3\x15\xd2\x0e\xefL\x18XC*\xbe\xde*f\u0a61J\x03\xae(c\a\xbf\xee\rq\xd1\xe7\x8aӵ+\x85+YA\rD\x03\x8c3\x8c-\x1f\xc7k\x84\xc5wX\x99$G\x92^\xd9B=v%cT\xacǞ\x17M\x98\xea\xe4\x03\xa3\xce\"\x17\xb41x\x01\x06\xe9\x88D4\x1e\x06>ڻ\xf7\xc6\xe8\x00\xec8\xa7\xf92f_0\xa7\r\xad\x13Q¼\u07b99\x04\x83\xcf\x02\xab\xb2Ww\xd7\x7f`1\x16ؑ-ձ\x98:\xe9{w\xb0\x1d\x18t\xd5-h(\tl@\x10+\x8a\x94q(\xa78\xf5+&\x92\xd5\x06\xd4O:\xc2\xc1J@\xcb\xe2O\x86*\x13\x97~\xe8Ǭ\xa4\xaa\xa9\xb9\"%5\xb0\xb0\xa3Os\xdd\xd2Ϥ*u\xe2q \xdel\xf3\xe2Q\x84k7\xd6\xfa\xb9\xfbh5hM\xd7!\b݂\x02\xb2\x06a\xf1\x1es\x8bI\x8f)\\\xe9\xf3\xc6\"\x96\x96Z\x14\xd2´\xd4O\xe0\\\xb8xz\x1a\xde'\xc6(v=\xaa\xa2Ӫ\xc2_\x1e|\x04\xaa\xf7\x9f\xbb>\xc0ŧ~_\x9f$v;vg#\xd4\x15x\xe2\x83dž\xc5\xc8:%\xd3F\xe2\xccG\x99\x93J\xca\xe7,7\xfbs\xecإ\x93\x98p\xac\x84W&\x97\xb25=?\xc7#<\xb1L|\xfe\xf3\x95\xed\v¼v\x17\xa8\xc6r\xaby\x9e\xde\xe7\x01\xa4\x18\xdeJCy02\x96/c\x87j\xe2\x01\x81\xa7\xf0x2绋}\xc8{\xaf\xb2w\xb0\xab\xee)O\xaf\t\xba\xeb\xe3ciU\x9f\xf5K\x02\x89\xaf\x80v>\xc9؛\x8bs\xf6\x0f\xa1~\xc2Ee\xe0\xf8s\xd7{\f\x8fn\x99\xcea\x06\x91\x8e4\t\x06\x1f\xa6\x8a\x92q\xc2\xd2'\xbcԦ\xa2z\xce=}\xb0}\xa2\xdb\xd13W\xd1\t}\x1c\x91\xca\xf4=\xd7\x05\xb9\x87m\xe2\xabC\x16\x9e~\xa1T%\xba܉\a%\xd7\n\xf4!\xd3-\xf0>#\x13\xebOR=\xf0v\xcdė\xf1\xca\xef\xa9\xce\x0fT\x19f\x99֭'1\xf6&ظ\xc4o\xf3\xa3\xc7\x7f`\x82r\xf6{J\x97\xf7\x7f\x9c\x9baB\xdf5\x1ey\xa7X\xa8\x80\xf89\x05\xe85\xf4O\xbag~¼\x97\xe4^&\xc5\xd8\x1f\x10\xb3!P\xa6\xc9\x12\xb4Y\xc0j%\x95q\xf9\xfbł\xb0Up\x90\xac\x86\xc08ѽfOX*\xf1\x1e\x8fނò\xf2\xa9D\x85V\aCΚ\xee\\F\x92\x16\x85\x8d\t\xe0\x8364\x15\x9b\xbcHOc\xa8\xeae%G\x85\xdc\xf5\xfb\xc7\x1c_T\x1f\bΡ\x0e\xaf\xb3;\x83\xce\xc7δ\x06\xafe\x10m\xb1w\x8a2!N\x8dݍ\x87\xddy\xa6\xe6k\x842\xa6\x1e\xfd\xfe\x06\x0fq\xfb\x03V\xdfɒ\xad\xa8\xa8X\x8f^h\xab\x94l\xd7U\xe0\xcd1\x87\x88\x94-F\xce\r\xaa\x02\x1d\xfe\xe3\x10\xd3*\xd1;\xb4\xf35\x16cZ:.w\xdcGy\x81\xa2V\xddŖNUM\xd8\xfc\xec,\xe1\b\xc4Y۟\x80H\xf5N\x14\x93Wp|\xa0\xcd&\xee\xeaNa(\x89\x84\xa8\x8d_\r\t\x11\xe2\x18\x12\xfa\xbeD\x17\xf1\xfc0\x18\x19\xf3QNDǴ\x13\x83[\x9c\x065\xbf\xe9\xbe\x134tw\x8eC\x87\x1e\x04\x7f'\xa5\xdd\x06\x10\x8e\x89|q\xeet\xdc\xfb\xe3F\xac\x9b\xe8mݞ\x1c\xbb~ۃ\xb1w\x05\xd2F\xb1\xdd4!\xde\xfcg\xb6Jɋ\xfbߙ\x96\x1c\xfe\xe5\xe0\xd77\xbeʸ\xa5J0\xb1>\t#\xbf\xfa\xb1\x89xރ=gD\x1fV\xfej1}\xd2,\x1d|D\x06/{x\xf63\xf9/\xff\x17\x00\x00\xff\xff/\xccd\x1aCm\x00\x00"), + []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xdc=Ms\xdc:rw\xff\x8a.\xe7\xf0v\xab4\U000bac87\x94n\x8al\xc7\xca\xee\x93U\x92\xe3wƐ=C\xac@\x80\x0f\x005\x9eM\xf2\xdfSh\x80\x9f\x03\x92\x98ч\xfd\x82\x8bjH\xa2\x01t7\xfa\x1b\xd0j\xb5z\xc3*\xfe\r\xb5\xe1J^\x00\xab8~\xb7(\xdd/s\xfe\xf0o末w\x8f\xef\xdf\x02}\x8fځ\x01S\xa8Z\xe4\x8e\xf7\x1eQ;dej+\xf9?[\xd8\xc6-\xdc\r*\x98Ec\x81K\x8bZ2\x01\x8fL\xd4x\x06L\xe6#\xc8%ۃF7&Բ\a\x8f:\x98\xf1<~%\xe2ɍ\xba\x80\xc2\xda\xca\\\xbc{\xb7\xe5\xb6\xd9Q\x99*\xcbZr\xbb\x7fG\x9b\x83\xafk\xab\xb4y\x97\xe3#\x8aw\x86oWLg\x05\xb7\x98\xd9Z\xe3;V\xf1\x15-DҮ:/\xf3\x7fi\x89:\x18\xd6\xee\x1d\x8f\x1a\xab\xb9\xdc\xf6^І8\x82h\x8cd\x9a\xfc\xbd\xdf\xeb\f\xf8\xa6Ez~\x06\x1b.,\xea\x11\xf6O\x12\xf5\re\x9e\x03\x19)Z\x0f(\xd4c\xb3\xe2\xe3wg\xe2\x98.\x8e\x99\x88\x97qgo\x1b7\x1e\xc4P=/\xc0\x05\nyp\x8d%\x85R\xe0+a\xb3{BF\xf5\xe5͇\xc3pǸ%p\xde\xc1B\x166\x9do\x97\xa3\x15\xf5\xe7\x17\xbc\x82\xe6\r\xd9@\xadS\xe5\xc3fg\xc0\xe0\x01\xf7\xdeta\x12\x1c}X\xf3q\xc2\xf0\x1a)~G|\xf6\x80{\x02\x13\x0f\xc8\x1d\xb6Tn\xf0\xed\x01#\xa6\x7f\xac\rp\xe8\xe6\x14\"\x1b\x1eO\xee\x01!\x82\xc20\xa9l\xe0[\xd8\n\x91\xf0W\xbc%ʒ\xa65\xb8?a\x99I\xac\xd2\x1f\xa3\x1f\xbd&\x0e\xf8\xc5xZ\xba\x1dS\xf0\x10\x966H{&\x95\xa0\xbe}c\x82\xe7\xed@~\x8f\\\xcb3\xb8Q\xd6\xfd!\a\xcd\x10\xa3|Phn\x94\xa5'/\x82Q?\xf1\x97ħ\x1f\x816\x9a\xf4R\xde!\xac\x1f\xb6\xf5:\xcdq[\x8b{n\xe0Z:\x7fţ$q(\x8a\xd0\xfb\xe1\xfc@em(\xe2*\x95\\\x91Ό\x8e\x14\xf0\xad\xf4\x00\xddO\x1e4\f\xf8\xd5)\v\xff\xc6\xe7\t\x04\xcb0o\xf0*\xabR9\xec\n\xd48`\x8cø;Y\xaaR\xd9^\xc8\xe2\b\x83\xb4R\xf9/\x066\\\x1b۟\x82\x81ڤ\xd2\xfaH\xf2\xb9y\x7f\xe5%\xaaھ$\x82?v\xc3\f\xca\x05J\xf6\x9d\x97u\t\xacT\xb5W斗mb>\xa0wǸm\xd3V\x14\xbf\xb1ʑ\xa0\x12h\x11ָ\x89\xa7\xecc-S\xd2\xf0\x1cuSh\xe2\xc9ƕۘ\x1b\xc6E\x1d\xcb\x12\xc5ڱ\x1e\xb0\xfc\xa8\xf5I\x0e\xf0\x17߳\x17w,\xd4n\x88\xa0ĵS\"\r\x81o\x80[@\x999\x8c\xa3\xf6\"\x99\x86\b\xc8 \xd4\xf0T9\x97&\xc0]CY\x97i\bXц\xe4r6\xe4\xd6\xff\xfc\x13\xe3\xe2%\xc8\xe68\xef\x93\xd2w\xc8\xf2Sb4\xbf\xf5\xba\x03JSkJ\xfe{ٱ\xe3\"mΎr X-\xb3\x02s_21\x90\r\x1e<\x97\xc6\"K\xe5\x05g\x15\xd5Rr\xb9M\xa3]r \xb4k\x1e\xd5k\xa5\x04\xb2\xe9,d\xd7\x1c\xae_A\x12\xfd\xd6\r\xf3DI\xd4\x11\xc1\xa7͉\x0e\xc9\x14uB\v\x98\xb5XV~\xcb)е\xeck\x97\x17\x10DǸ\xe1a\x16\xcf\xe9_s\xc9\x13h;\xa0\xeb\xb5\xe4\xb6o<:\x10/j<\xba\x01Zs\xe0\x94\b\xdb\xf5\x00\x80۠\x8d\x1fBso\xb9\xe6\bCr\x8d\xc0\xf2\x1cs\x1f\xbbt\xa6HpK|\xed\xe2DqCtu\xc7[\x82I\x94m\xda\xc0\xe9\xa48\xac~\xc4U-\x1f\xa4\xda\xc9\x159\xe3\xe6h\x19rb\x94\xea\xa9\xc3ۓ\x85Ѳ|I\x17\xd3KRhȯ\xe9<\xd5\xd8O/ e\x92\xf9樀\xc7\x1c\x17,\xc95_C?\xf1rq\x16s\xe3\xcft\x0eI\xe9+_\xef\xfe\xa4\xb2\xb8\xeb8\xa8\x9eQ\xb8+\xd0\x16\xa8\x9b\xea\xfa\x15\x9d*\xc8g3\xa4\x9d\xf3\xd2\xd6\xc99\xa6jLd_\xc1;\xaa\x9c#\xef\xa6\x16\xe2\xcc\xf16\xabE\xd4\x1d\xb6\x8a\xb6\xd8!g%Տ\xc5-\x86\x94\xea\x8bd<\xf6+-\x86\xf5\x85m\x15DS`\xa8\x9a\x91\x03\x8dc\xeb\xa5\xda\xe0^~\x7fXNA\xf1\xbff\xfa?\xbc\xf40\xa1R\"\x1d\x8d\xa9U\x9a-\x12#\xb0\"\f\xd6CcW_\x11\xbe\v\xb5\xda?\x17N-\x96_\xaa\xb0c&M\xd8\x04\xb4F\xe0\x8c\xeaMH\x1b\xd4ƛ\x02\xad\x1e\b1C\xd7\xff2\xf3\aY\x1a01~\xfdZ`\xb3}\xc3\x01\fn\xe0\xafP\xa8:R\xd57\x83\xb2\x85\xea\x8e\xe5\x05\x0f\n=BB\x01-{|\x7f>|cU(\xfb\xa0(Z\x04\x109E]d\x96˜?\xf2\xbcf\xa2ٵ\xdd1\x10\xcf@\x1d\x9fE\xa0)\r\x92\vπM\xff\x01\xc3\xc1\x97ʧe\x8e\x16q\xf3\xb6hZu\xc8\xc95!Ú\x8f\tmxl\xfa\xe2Y\xaa`\x7fH\xad\xc7\xf1\x15\x1e)\x9e\xc4B5\xc7\t5\x1c\x89\xc5bOη\xa4Ti\x1c\xe3s\xbfXE\xc6\xf3\xd7a$\xe1g\xb9\xe6\xe2\x18\xec\xbcx}\xc5+VU\xbcN-Eb\x05\xc5\xf3\x95B\xa6y\x9f'\x95\x02,;,\xd3U\x10\x8b\xb5\x0fOrhNZ\xd2bM\xc31\x95\f\x8b\xd4I\xdbf\xafV\xab\xf0j\x15\n\xaf[\x970\xcbE\xb3/\x8f\xa9\xfe\xf3\xfe\xcbM\v?f\xf3\x06\xcbxt\xbd\x84\xb7`\U00080710\x9a\v\xc5L\x1e[d\x03\xaaΦ\xae\x84b9\xea+%7<\x92!\x19\xa0\xf5\xbf\x06\x1f\x8fx6\xa3\x87\xb5\xeen眽\x16\xefI\x92\xabb\x9a\t\x81\xe2\x13\x17h>\xa8\x9dt\xf3Jؐ\xb7\xb1~\xbdsYY\xad\x9dZ߃\xac˵3r\xd1\xdaigq\xa3\xf4|\x85\xb4\xc7;\x97\x16\xb7\x18\xf3\xafw\x9a[\xbc\xaf\x986H3JX\xc1o\xa3.\xde\xfb\xdc\b\xb6\xf5\xa5p9Ϙ\xc5V\x01\xd3\bSӧ\xfe\x86`\x89=U&\xa9\x89\xa0W\xf2\xa6\x9e:\x921\xb9\xad\xa7n\x88\x8d\xa8\xea\xe8\x1d\xb1^#g\xac\xb2t\x00\x86\xe8HD\xb4\x01\x06ݻ<\xba&v\x00v\x9a\xd3B\x19s(\x983\x96\x95\x11/aY\xee\\\x1d\x82\xa1\x9b\x9duޫ\xbb\xeb_\xb0\xd8\x16\xd8\xc1\x8e\x99\xb6\x98:j{w\xb0=\x182\xd5\x1dh́nAu[\x91q\x81\xf9\x1c\xa7~\xa5@\xb2~D\xfd\x8bi\xe1P%\xa0c\xf1{˴m\xa7~h\xc7l\x94.\x99\xbd\x80\x9cY\\\xb9ާ\x99nQ\xf1D\x87\xc7N\xbb\xed\x93z\xfa\xed\x915\xc7n\x9c\xf6\xf3\xe7\xd1J4\x86m\x1b't\x87\x1aa\x8b\xd2Ὅ-F-\xa6\xe6H_P\x16mi\xa9C!\xcbl\xcd\xc2\x00ބk\xb3\xa7\xcd\x15\xd3\xc6\xdfj;%\xa2\xe3\xa2\"\x1c\x1e\xbcCf\xc67\x96\x1f\xe0\xe2S\xff\xdb\x10$\xf6+\xf6\xb9\x11\xe6\v<\xe9\xcej\xcb[\xcf:\xb6\xa7\xad\xa2\x91\x8fR'\x85R\x0fIf\xf6\xe7\xf6\xc3.\x9cĥg%:2\xb9V\xb5\xed\xd99\x01\xe1\x91i\xd2\xf5\x9fϬ_\b\xe6\xa5?@5\x15[M\xb3\xf4>\x0f \xb5\ueb72L4J\xc6\xf1e\xfbA1s\x81\xc0}s\xff\xb5\x10\xfb\xb31\xe4\xd1\xc5\xfa\x1d좻\xca3H\x82\xee\xf8\xf8TX5D\xfd\xa2@\xda[@;\x9bd\xea\xce\xc5%\xfdGP?Ѥ\x12p\xfc\xb9\xfbz\n\x8f~\x9a\xde`F\x19\xf74\x81\x9c\x0f[\xb4;ㄩ\xcfX\xa9U\xc1̒yz\xeb\xbei͎\x9e\xbaj\x8dл\x89]\x19?纂\x1b\xdcE\x9ezdQ\xf6\x8bvU\xe4\x93ky\xab\xd5V\xa39d\xba\x15\x9dg\xe4r\xfbI\xe9[Qo\xb9\xfc2]\xf9=\xf7\xf1-Ӗ;\xa6\xf5\xf3\x89\xf4\xbdjt\\\xe4\xddr\xef\xe9\x17\\2\xc1\xff\x19\x93\xe5\xfd\x97K#\xccȻ* \xef\x14\r\xd5 ~I\x00\x06\t\xfd\x8b驟f\xdcs\xb8Q\xd1m\x1c\x12\xc4|\b\x94\x1bX\xa3\xb1+\xdcl\x94\xb6>~\xbfZ\x01\xdf4\x06\x92\x93\x10\xe4'\xfa\x7fH\x00<\x16xoSo\x8d\xc1\xb2\t\xa1DMZ\x87\\Β\xed}D\x92e\x99\xf3\t\xf0\x9d\xb1,\xe6\x9b\xfe\x87Y\n\xf5f\xf7\xf6\xe2Q\xc8\xfc\x9a\xdd\xd4ƪ\xf23\x18U\xeb\f\xde\xc3FHa\x85\x92\x17%X\x9es˯/\x18\xe3R*\xcb\xf1\xb3\xc1?\x19˔\xb4Z\x15\x05\xe8\xc5\x03\xc8\xe5c\xbd\x86u-\x8a\x1c4\x01\x0f]\xef~X\xbe\xfd\xcb\xf2\x87\v\xc6$/ᚙl\vy]\x80Y\xee\xa0\x00\xad\x96B]\x98\n2\x04\xfa\xa0U]]\xb3\xf6\a\xd7\xc8w落\xf3\xed\xe9S!\x8c\xfd\x9f\xde\xe7\x8f\xc2X\xfa\xa9*j͋N\x7f\xf4\xd5\b\xf9P\x17\\\xb7\xdf/\x183\x99\xaa\xe0\x9a\xfd\x8c]U<\x83\xfc\x821\x8f?u\xbd`<ω\"\xbc\xb8\xd5BZ\xd07\xaa\xa8\xcb@\x89\x05\xcb\xc1dZT\x96F|g\xb9\xad\rS\x1bf\xb7\xd0\xed\a˯F\xc9[n\xb7\xd7li\xa8\u07b2\xdar\x13~u$r\x00\xfc'\xbbG܌\xd5B>\x8c\xf5\xf6\x8e\xddh%\x19|\xad4\x18D\x99\xe5\xc4@\xf9\xc0\x9e\xb6 \x99ULגP\xf9O\x9e=\xd6\xd5\b\"\x15d\xcb\x01\x9e\x1e\x93\xfe\xc7)\\\xee\xb7\xc0\nn,\xb3\xa2\x04\xc6}\x87\xec\x89\x1b\xc2a\xa34\xb3[a\xa6i\x82@z\xd8:t>\x0e?;\x84rn\xc1\xa3\xd3\x01\x15\x84w\x99i \xb9\xbd\x17%\x18\xcb\xcb>\xccw\x0f\x90\x00\x8cHT\xf1ڐp\xb4\xado\xbb\x9f\x1c\x80\xb5R\x05py\xd1Vڽu\xb2\x97m\xa1\xe4\u05fe\xb2\xaa@\xbe\xbb]}\xf9\xf7\xbb\xdeg֧\xe8\xff-\x9a\xef\xac\xe1\x06\x13\x86q\xf6\x85f\t\xd3~\xda2\xbb\xe5\x96i@1\x00i\xb1F\xa5a\x11H\x9d3\xa5;\xa0*\xd0B\xe5\"\v,\xa2\xc6f\xab\xea\"gk@n-\x9bڕV\x15h+\xc2Y-;\xf0\xa8\x81\x19\xe2\xf1\x93\xd2\xc0\x84ܨk\xb6\xb5\xb62\xd7o\xde<\b\x1b\x94n\xa6ʲ\x96\xc2\xeeߐ\xfe\x14\xeb\xda*m\xde䰃\xe2\x8d\x11\x0f\v\xae\xb3\xad\xb0\x90\xd9Z\xc3\x1b^\x89\x05\rD\x92\xe2]\x96\xf9\xbf\x05~\x9b^\xb7\a3\xd3\x15R\x993\u0603\xba\xd4I\x97\x03\xe5\x86\xd8r\x01?!\xe9>\x7f\xb8\xbb\xefJ\x9e0\x9e)\x1d\x01\x8c\xf1\a\xa9)\xe4\x06\xbc.\xd8hU\x12L\x90y\xa5\x84\xb4\xf4GV\b\x90\x96\x99z]\n\x8bb\xf0[\r\xc6\"\xeb\x86`o\xc80\xa1\xd0\xd6\x15\xce\xdd|Xa%\xd9\r/\xa1\xb8\xe1\x06^\x99W\xc8\x15\xb3@&$q\xabkn\x87\x95\x1dy;?\x04\x9b\x19am\xd0\x15w\x15d\xbd\xa9\x86\xed\xc4FdnB\xa1JnT\xc9@-\xbb2>\xfb\xe9\x17\xd2}ï\x03<\x9c\x82\f\xbd\x82A\xa3d\xb7\xc4\xfc\xd66\xa2\xc89hLi&\x95=\x80y\xa8Z;\x94\xf0P&09\x10vv\xa0RS,\xe9\b\x90ֶ\x0e\xe5+\xcaj\xc2\xfbQT\xab\xb2\x84\\p\v\xc5\xfe$\xf4\xfb \xc6Ȭ\xa8\x1f\xb6vz^lzD\xcfk`\xa2Ӟ&\xe3_C\x8dCk\xfcW\xb2\xecdD\x1dM\xba\xc0j\xd9\xf2pЏ\x84\xa7C\xd20\xb6\xda0\xabQ\xe7z\xec\x9eDQ\xe0LF\x8c+\xc8{\xa8Ż\x13\x1b&l\x18͚\x13\x06\x92-\x9d\x17\xb5l}\x86\xc6\xfe#\x82\x03\xecH\xed\xbb\xfe\xd1S\xe1\x96I\xf8j\xdbZ8\xec\xc8\b6\xbc0\x83!x\x854k\x18Wl]\xdb\xd30\x80\xb2\xb2\xfb+\xd7v\xa3\x8aB=1C\xca\x16\x8d\xe0F<\xd4\xdaM\xf6?\xe6\xb0\xe1ua\xaf\x1d\xce\x7f\x8aI\xeb\xf84\xb3PVh2O\x91\xd3{\xdf\x16\a\x8c\xb3%ob\x8c\xe0&\a?Dy\xf7c\x04\x88r^l\xa5\xd5N\xe4ޜ\x1f\xa8+vTeaɌ\xb8\x93\xbc2[eQ\"Tm\xc7j\xa5\x8c\n\xcb\xcd\xddj\x00\xad3\t\x11]r\x85IN\xadbO\\Xҹ7w+\xf6\x05c\b\b\xad\x99\x9bl\xcc\xd6Z\xa2\x9d\x8b\xf4\xf7\x19x\xbe\xbfW\xbf\x18`yM&:\xb8\xb7Wl\r\x1b\xb4g\x1a\x10\x06\xfe\x04Z\xa3~7\x84\x84\xaa\x0f\\\xa6\x86=\x8e%(\x1b\xde\xe2\v\xc3\xde\xfe\xc0J!k;*uG\x15\x1bQ\x8f[^\xaa\x1d\xe8\xe7\x10\xf7=\xb7\xfc'\x042\xa0)\x02g\x04\xdd\v\f\xd1w\xbd\xa7\x1f\xd7\x11M\xec\xcajӁ*\f\xbb\xbcDmp\xe9B\xce\xcb+\a\xa1\x16\x85]\b\xd9\xed'\xa8&\xec\xe94\x828\xfa:\xa6\x9b{\xf5\xa3q\"\xff,\xfaD`\x8e\u0601J\xe5lG\xf5\xd8F\x14\xc0\xcc\xdeX(\x83\xd6j=\xffN83,\xe4+\x14\x85\ac\x90\xde~P\xe3\x04\x91uQ\xf0u\x01פ\xe4\x8f\xd0l\\ߌ\x11\xed3\x18+\xb2s\x92\xccA\x1c!\x98\xf6?\xf4(C\xa1\x03\x7f\x04\xc6#\xe0==1N)\x8a\x0e\xd1\xfbԺ\x88\"Wi\xc8Љ\xbd\xf6α\x80\x82\x1cr\xa9X\xa1\xe4\x03h\x87Fc\xacPY\x02Jh\xce\xd0\xef\xd4hb\x84d\x9b\x1a]\xd2%C5\x11\x15\x12!\x8d\x05\x1e\x91\xe630\x0f\xbefE\x9dC~S\xd4Ƃ\xbe\xcbT\x05yXe\x1aUͩL\xfcp\x14\xb2\x0f`\n\x91\x012\"s\x95\x16\xb4\xca\x13\x93\xed6\x96\xd9W\xe0\x16\x9d\x90\xd7~\bm\x902\xa9\\\fXlx\xf9\xe7\xcb+\x12\x81~\xef\xfd~\f\xe3\x1a\x1a2\xcdR\xced\xf2\xc7[\b\ve\x84\xba\x93Jj\x06߹\xd6|\x7f\x84\xeb\xcdj\xda\v\xf0=\x06{\xc0y\x19\xaa}#\xde\x0f\xfb\xffW\xe4\xfey\xf9mhՙ\v\x89|.\x84\xb1=6\x1b\xb7\x8c\x85d\x1d\x8b!=\x81\xa4\x83\x89jr\x8a\xab\xff \xc4<\xeb܉M\x96F6\xfd\x04\xf8\xa7\xa2\xe4V\xa9\xc7\x14\xea\xfd7\xd6kװXF;#l\r[\xbe\x13J\x9b\xe1:)|\x85\xac\xb6Q\xcd\xc2-\xcb\xc5f\x03\x1aa\xd1:\x7f\xb3-p\x8cX\xc7\xe3\x17\xd6QY\xd1\n\x83q\xb5LG\x96\x125bC\xa1\b5\n\xd5y8\x18[\x90\x03\x91\x8b\x9d\xc8k^\x90/\xc1e\xe6\xc6\xc7\x1b\xfcbZmB \x0e\xf0\x8fJ\xb5+Ρ\t\x83D&\xf6\x96\xbd\x94\x04t\xf2K\f\x8e\x0e\xab\xc6)\x11\xd6\x12\x8e\xf6\x8d\xcc\xd4u\x01\xc6w\x97\x93\x9f\xdc꤫\x96Yn\x91\xa1\xe0k(\x98\x81\x022\xabt\x9cB)r\xe0J\xaaҍ\x10wD\xcb\xf6ív0\x13`\x19Ÿ[\x91m\x9d\xfb\x8a\x82F\xb0X\xae\xc0в\b\xaf\xaa\"b\xba\xda2)\x1c\xbe\xb3)\xbdі\x04\r2\x84\x1b\xd3%mI\xd4\xcfm\x19%{;7\xfbT\x1f_\xe8\x1f\xc5\xf7_\x89\xe8\xc1\xea\x9c(\xec\x13\x9a\x84цA\xf2|\x88\x92\x1e).\xc0,;\xcbs\u0086\xaf)\f\xed\xf9\x8f\a{)\aD\xf9}\xf1\xee\xb4\t3\x83u\x93s\xeae\x19\xd7t\xf3O\xc272Yw\xdeb\xcd\xe2\xd9\xc7n\xcb+\xda\x16\xf0\fɯ\xd8F\x14\x16ȩ\x9aB\x94\xcd\xe0\xdc9\t\x94j\x81\x19\xed\x12\xdbl\xfb\xa1\xd9|\xed,Q\xa3v\xc1\xbfS\xa4\xf5\x14\x1c\x19\x1d\xd8(K>\xcc\aNF\xf7Ƶ\x0es\xcc\x03s\xe1\x96~\xa8I\xe7\xcc\xf1:\x1aQ\xfeGsmJ!W\xd4\x11{\xfb\x82\xee\x90\xd7\xe2\xb1\xfc\xa8\xb1r\xba\x93~\x13:k\xb9\xd7|\xf0Iu\x8a6~4\xf4\x98{\xb8'B\u07b5T\xb6\xb3\x8c3Ӊ\xaeT\xfe\a\xc36B\x1b\xdbE\xc3\x1cɬ\x1a\x05uB\xe8)?h}r\xe4\xf9ɵ\xee,(nՓϜ\x9e\x13o\a\x92n\xf9\x0e|\xea*\xc8LՒ\x96\xc2P\x0f`73 :\xd68+\x90h\xef:\x8de]\xa6\x13dA\x92$\xe4\xe4\xbaY\xb7ɏ\\\xa4\xad[\xb1\xd3\xd8j\x8f%q\x8e\x95\xd3\xe7Q\xc8\xf0\xec\xe6ӗ\xfc\xab(\xeb\x92\xf1\x12yHn\x87(\xa1I\xa9w\xecn\xf2>\xb1\x05\x19-\xabp\x96U\x05X\xf0y\x9b3\xf0Ȕ4\"\x87\xc6\xf4{\x11P\x92q\xb6ᢨ\xf5\f\xad:\x9b\xe4s\x830\xafM\xce\x1fY\xa5#\xb2 \x12%\xae\xb3\xcf\xf0\x82\xa75~\xa5\xe7\xf9\xb1)\x0e\xa3\x86\xf9\xfeb\xa5\x85r\xa7\x01\xce\xef2\xfa\xbcc.\xf7\xdf}\xc6\xef>\xe3w\x9fqNG\xdf}Ɖ\xf2\xddg\xfc\xee3\x1e/\xdf}Ɣ\xf2\xddg\x9c\x89ȷ\xf2\x19S0\\\xd0\x1a\xe7\x91\nIX%\xa6BL\xa1=їO\xfa\xf1g5Β˼\x1a\a9r\x8a'r\xfc\"\xe6u\xb4ƫIn\xc6\x19\x18\xe6\x8e;F\x99\xe00\x9f\xe1\xf4L@\xe0\xfc\xa7gVG!\x9f\xf1\xf4\x8c\x1fBZ\x84q\xd2ٙ@\xa4\xf9\xa7'\xae|\x12Q\t\xaaA\xfe¶\xaa\x8e\x9cژ mB\x16m\x1aAzI\xb5>1\x02,߽]\xf6\x7f\xb1ʧز'a\xb7\x11`t!\x05\xcfs\x8c\v:\az\xbc\x1e\bw%\r\x852\x02Li&E\xe1$6@\xe8\xc9+\xfbT\xb9\xd5\xc1\x93\xfd\xa6\xe95\xac\xf4Dܹ\xe9\xb7M\xb6\xe4\xb4\xfb\xfe\x8c\xa4۳\x1e\x8d\xfafi\xb5\xa7%Ӧ\xaeP&$Φ\xa7˦\xb0Օ\xf4$\xd9\xe4\b95!v\xee\nċ&\xbf\xbeL\xcak2\xcd\xd2\xd2[\xe7R\xecURY_9\x81\xf5\xf5\xd2Vg$\xab\x9e\xff\xd4K\xfaZ\xfa\xc9ٕi\xcb2\xc7\x13N\x93\xd2L\x93\x96nR\x06|\xd2P\x93\xd2G\xe7&\x8d&q2}\xba\xbejZ\xe8\xab&\x83\xbe~\n褴MV\x98\x9b\xe49~\xcba(\xd3\x0e@\xf1-\x84\xf3\xb9dR\xba\xe7\x9a?+\xee\xfc4\x80\x85\xc2\x12\xdc\xd4W\x8c\x03ʺ\xb0\xa2*\xda\v\xd9b\x01\xe7\x16\xf6\xcdeE\xbf*:\"\xef\xaf\xea\xfa\xf4\xb9\x91\xf8\xe5 \xaa\xe1\x86=AQ0\x1e\x9b\x9b\aT\xc8\xdcE\xa0\x99Z\x00\xdaF\x9c\xe5\xfe6&\x7f{蕛.t\x1b\x00Y\xd82\xb6\xd4\xc7\xe5\U0006bf8e\x1a\xb0T=v\xe0\x99\xbbx\x83\xbe\xfdV\x83\xde3\xbax\xac\xf1\xcd\xdaC\xa5~\xa2\x1b\fL\x83\xfa\xf1\xea\xf0؞\xc9A\x80Ӫ\a\xf6N:\x8f`\x88\x13\xb5A\xbd\xd3\x06t\xa8T1N\x8b\xf6\x13\x01!U\x03!\xd24\xc5\xf9\x9fs\xca\xf2%»s\x04xI\x1e\xd0<\xef\xf5\x1b\x9e\x9e<\xf5\xd4dz2J\xd2)ɗ\b\xf7\xe6\x04|\xb3\xfc\xd5\xf4S\x90\xf37\x9e_\xf8\xd4\xe3K\x9dv\x9cA\xbd\xd4Ӎ\xf3i\xf7J\xa7\x19_\xfd\x14\xe3k\x9e^\x9cuj19=kV\xc6\xc1\x9cԪg\x1c\xb7K\xcb%\x98>\x85\x98x\xfa01\xd3 m\xf0'\x0e;\xf1t\xe1\xfcS\x85\x89\xfc\x9d3\xa5_\xf9\xf4\xe0+\x9f\x1a\xfc\x16\xa7\x05\x13$0\xa1\xca\xfcS\x81\xcfޒR:\a=\xb9\xed7Gj'\xe555\x96\xeb#6\xd8\xd7\n\xd7\xc9b\xad^\f@f\xc9\xdf\xe4O\xaf6\x1c\xdb\x06G\xc9\xecxD\xbd}\xc9\xd6]\xeb;\xc4\xfe9\a\xb7ui\xa0\xe2h\x00(p\xa3Ԭ\xa8\xab\xf0\x81g\xdbA\x0f[n\xd8F\xe9\x92[v\xd9l\x16\xbfq\x1d\xe0ߗK\xc6~TM\xaeN\xf7\xbe4#ʪ\xd8c$\xc6.\xbb\r\x9e'%Q\xe9\f=ߪBd\x11\x9fs\xf4^=\xd7\xe0\xe0\xb2!\xba\xf9/\xebd\x8b\xc4\x02\x1fl.\u00ad\x8b\xfd;\x99݅\xee'\xae\x95\xf0J\xfc\x17\xbd\xa9t\x86U\xb7w\xb7+\x82\x15Ĉ\x1ekj\x12\x14\x1b\x96\xaf\x01]\x86v\xec\xc7\xf4\xc9jӃ\xda\xcf\x11\xee\xbeV\x01\xb9{\x9a$\xb8-^5g\n\xb5\xd6\xed\xca\xe1r\xac'\x94/.\xf7L\xf9\xb7'\x84\xce\x17\x15\xd7v\uf489\xaezx\x04\xbb>\xb5jv\xd4Z\x1d>\xbd\xd2-=\xb2\x87WWh'{_\xf5\x93\a\x86\xf4|\x0eN\xc7OUO\x9e\xa7~\x01\x9c\x8e\xbbP\v\xa2b\xe4\xa7h\x06\xe4\xd9W,\x8d\xbf\xa2\xff'\xb5\x83\xf7ѕ\xcb\xfe\xf3+\x83&#\xa9\x89\x01*\xdd2\x1f\xa1`\x9b\x8fHw|?O\xed\xc5s\r\x03*\xfe\x8e\xf0\xe7,N\xde\xf5A\x8d\xbfHBW\xa8\x87Nc^\x15\xbd\xf5\xb4g\xb7_(nmT\xa9\x9f\xfa>n\r˓!\xc1 \x02Kȣ\x8f\xb4\x9c\x8b\x8cVi\xfe\x00\x1f\x95{\\'EL\xfa-zO/y\xcf-\xe4k\xfbI\x18S\xf4~lC\x80\xed\xf9\x8c\x83\x9b\xfe\x11\xdb\x13\xdf2\xb0\xb6x\x8e\x8c\xdc\xdf\x7ft#\xa57M\xde\xfb\xe7IP\x1f\x1b@\x16\x04\n8hk\xfc\xefV=\xd1\x05\xf8\xf15\xe6\xf0\x82H\xe7\x113\xa0\x83\"\x94\xc2{\xd20\xeb\xaaP<\a}C\xaf\xa8$\x8c\xf8\x97^\x83\x81;\xd0\x7f\x8b\xc5\xdb\xcd\xc8xB\xcf/\x98%\x83\x1e]Q@\xf1\xa3(\xc08\xc4\x13M\xc3\xeda\xcb\xc6R\xd4\xe5\xday\xaa\x1b\xfc\xb1\xe9\xe4\x88evC\xa5\r\x86\n4\xfa\x89n+\xa26A\xf2\x8f\x13\x835|\x14\xd2\xc2\x03\x8c\xc7\xd0\x136a\xd7{\x8a%̞\x14E\xf8e\xbceǙ\xee\xccc\xf2~\xe3\xea.\x06\x8b\x1b\xa32A\xfe\xf7\x93\xb0\xfe\xe2×\xbbm\xfbX(u\x84\x8e\xb5\x81OO\x12\xf4砫\xcdJƞ8\x99\xd6\x13\xbf\x1c@\x8b>mb\x15\xf6=\x02c\x00\x80\xa9\xb0#dܣ9a#J\x98\xe6\x1d\xb0CzNL\xb6\xb8M\x18wm\x16\xe3\xcf\x16-\x9a\xe7\x95.\x12\xc8\xed\x9e\n\xea\x03\x1e\x7f\xfdͽ)\x94\xf1\xca\xd6:\xe8\xa1Z\xd3}\xe4\b\x04\xdcuݧ\xbd\xff\xd6>\vv\n\x83\xdbw\xb9ڕ\xfaɗCG\xe04/\xb8E\x9f\x83r\xb1\xa7{\xd9s\x81\xf0O\xe3\xf1\xe8\x8cA\x9c\xef\xdc3_\x13D\xf8\xd8\xd6\x1c\x1bp3\f\x1c\xb2\x7f8\xecUGB\xd7\xd3O\x8c\xe1\x16\xeb4\xe7A\xbd\x1cQ\xc3p\xad\xfd]\x8c\t\xe3\x87\x06\x17\xecg8\x8cm\x17\xec\x83\xc4A\x1c\x12\xc0\x9d\f\x84\x9c6!H;\xce\x19\xe2\xaeiE\xc72G4\xe4\xb4\xd8~\x19\xc0\x18\xe4|\xd3\xfbHM\x15w.Ӱ?\x8a1\xbf\x8d\xf6\x962\x1c\xe8\x9f\x0e~\x8dj\xf0\xa3\xda;\xa6\xb9G\xd5\xc8\xc1Gz3.\xefH\x8e\xf7g\xbb_\xeau\xfb\xf4\x00\xfb\xdb\xdf/\xfe?\x00\x00\xff\xffgH\xe37iz\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcV\xcfo\xeb6\f\xbe\xe7\xaf \xb0\xeb\xec\xbcb;\f\xb9\r\xdd\x0eŶ\x87\xa2y\xe8]\x91\x99\x84\xab,y$\x95.\xc3\xfe\xf8A\x92ݦ\xb6\xb2\xf6\xed0\xdd,\x89\x1f?~\xfc!7M\xb32\x03=\"\v\x05\xbf\x013\x10\xfe\xa9\xe8ӗ\xb4O?HKa}\xbaY=\x91\xef6p\x1bEC\xff\x80\x12\"[\xfc\t\xf7\xe4I)\xf8U\x8fj:\xa3f\xb3\x020\xde\a5i[\xd2'\x80\r^98\x87\xdc\x1cзOq\x87\xbbH\xaeC\xce\xe0\x93\xebӧ\xf6\xe6\xfb\xf6\xd3\n\xc0\x9b\x1e7 \xc8\xe9L\x8dFa\xfc#\xa2\xa8\xb4'tȡ\xa5\xb0\x92\x01m\xc2?p\x88\xc3\x06^\x0f\x8a\xfd\xe8\xbb\xf0\xdef\xa8m\x86z(P\xf9ԑ\xe8/\xd7n\xfcJ\xe3\xad\xc1E6\xaeN(_\x90c`\xfd\xfc\xea\xb4\x01\x11.'\xe4\x0f\xd1\x19\xae\x1a\xaf\x00Ć\x017\x90m\ac\xb1[\x01\x8c\x82d\xacf\xd4\xe2tS\xe0\xec\x11{S\x9c\x00\x84\x01\xfd\x8f\xf7w\x8f\xdfm\xdfl\x03t(\x96i\xd0,\xeb\xdf\xcd\xcb>\xd4\xc2\x04\x1200R\x02\r`\xacE\x11\xb0\x91\x19\xbdB\xa1\f\xe4\xf7\x81\xfb\x9cV0\xbb\x10\xf5\x02U\x8f\b\x8fY\xff1\xcc\xf6\xe5p\xe00 +MҔuQq\x17\xbb\xffF<\xad\x14k\xb1\x82.\x95\x1eJ\xf6<\xea\x85\xdd(\x0f\x84=\xe8\x91\x04\x18\aFA_\x8a1m\x1b\x0fa\xf7;Zmg\xd0E\x17I\x99\x8c\xaeK\x15{BV`\xb4\xe1\xe0\xe9\xaf\x17lI\x02%\xa7\xceh\xd6\xce+\xb27\x0eN\xc6E\xfc\x16\x8c\xeffȽ9\x03c\xf2\t\xd1_\xe0e\x03\x99\xf3\xf8-0f\xa97pT\x1dd\xb3^\x1fH\xa7>\xb4\xa1\xef\xa3'=\xafsK\xd1.j`YwxB\xb7\x16:4\x86\xed\x91\x14\xadFƵ\x19\xa8Ɂ\xf8܋m\xdf}\xc3c\xe7\xca\x1b\xb7zN5(\xca\xe4\x0f\x17\a\xb9u\xbe\"=\xa9\x91J1\x15\xa8\x12\xe2k\x16\xd2V\x92\xee\xe1\xe7\xed\x17\x98\x98\x94L\x95\xa4\xbc^]\xe82\xe5'\xa9I~\x8f\\\xec\xf6\x1c\xfa\x8c\x89\xbe\x1b\x02y\xcd\x1f\xd6Q.ܸ\xebIe*픺9\xecm\x9eU\xb0C\x88Cg\x14\xbb\xf9\x85;\x0f\xb7\xa6Gwk\x04\xff\xe7\\\xa5\xacH\x93\x92\xf0\xa1l]N\xe0\xf9\xe5\"\xef\xc5\xc14;\xaf\xa4\xb62%\xb6\x03ڔܤo\xb2\xa6=\xd9\xd2V\xfb\xc0`j&퇘d\x8b\xaf\xe42N\xa4\xc2f6\xa7R\x97\xbfϦ>\x96\xf2\xc9\xd1\b\xce7g\x9c\xeeӝ\xb9\x7fG{\xb4g\xeb\xb0@\x94)\x84\xefSI\v}\xec\x97>\x1b\xf8\x8cϕ\xdd{\x0eiB\xe3|\xd4\\\xad\r(\x8f\u0601\xfc\"\xdcyd\xe5V~\x18\x97#?\a4\x02\x01G\xefSK\a\xbf\x80\xac\xbc\b\x8b;\xa4\xd8W\xd8T\xf9\xdc\xf9}\xc8\x7f\x11&96Z\xda\t\xc7d\x8f~\n\xaf\n\xe0\xf5\\\x97\xb5\x9cs\x1f\x12\xb4\xac\xfc<\xff7\xe34\x97\x88\xb1\xea\xbbɬ\xaa\a\xc9cM\xf1z\x7f\x8d,\xa3sf\xe7p\x03\xcaqi]l\r\xb39ϫf*\xb5/ԣ\xa8\xe9\x87w\nh\xf1*\xa4u\xbf@I\xcd\xf3|D\x7f\xadE\xe0\xd9ȫ\xf3\n\xe4\xee|\xcd\xf4\xf6\xe5os\xd9g\xa5\x9e7\x90f}\xa3T\x11\xf2CJUSZ\xea\xbc\xfa[\xb3Pi{yw\x1a$o\xfae\xfa\xabY\xc6p\x95B\xb5\x02\x16\x9b\x19\xbe\xbb\bO4\xb09L\x01\xff\x13\x00\x00\xff\xff\xd9Ո\xaf\x10\f\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcVM\x8f\x1b7\x12\xbd\xebW\x14\xec\xc3^\xa6\xd56\xbcXxuY\x18\xe3=\x18\xb1\xe3\x81\xe5\xcc\xd9\x14Y-U\xc4&;\xac\xa2d\x05\xf9\xf1\x01\xc9\ue65eVk<\x13\x04\xe9\x8b \xb2\xf8X\x1f\xaf^\xb1\xaa\xaa\x85\xea\xe8\x16\x03\x93w+P\x1d\xe1wA\x97\xfe\xf1r\xff\x96\x97\xe4\xeb\xc3\xebŞ\x9cY\xc1ud\xf1\xed\x17d\x1f\x83\xc6\xf7ؐ#!\xef\x16-\x8a2J\xd4j\x01\xa0\x9c\xf3\xa2\xd22\xa7\xbf\x00\xda;\t\xdeZ\f\xd5\x16\xddr\x1f7\xb8\x89d\r\x86\f>\\}x\xb5|\xfd\xef\xe5\xab\x05\x80S-\xae\xe0\xe0ml\x91\x9d\xeax\xe7\xc5z]0\x97\a\xb4\x18\xfc\x92\xfc\x82;\xd4\xe9\x8am\xf0\xb1[\xc1\xfdF\x81\xe8\xaf/\xae\xdff\xb4u\x8f\xf6\xb1G\xcb\x06\x96X~z\xc4\xe8#\xb1d\xc3\xceƠ\xecEϲ\r\xef|\x90\x9f\xefo\xaf\xe0\xc0\xb6\xec\x90\xdbF\xab¥\xf3\v\x00־\xc3\x15\xe4\xe3\x9d\xd2h\x16\x00}~2\\5\xa4\xe6uA\xd4;lU\xb9\a\xc0w\xe8\xde\xdd|\xb8}\xb3~\xb0\f`\x90u\xa0Nr\x96\xe7C\x04bP0x\x02\xc7\x1d\x06\x84ۜO`\xf1\x01\xb9w\xfa\x0e\x14`\xf0\x9f\x97w\x8b]\xf0\x1d\x06\xa1!\xf8\xf2\x8d\xf85Z\x9d\xf8\xf5G\xf5`\x0f \x85RN\x81IDC\x06\xd9\xe1\x90\x0e4}\xf4\xe0\x1b\x90\x1d1\x04\xec\x022\xbaB\xbd\xb4\xac\x1c\xf8ͯ\xa8e9\x81^cH0\xa9Vњ\xc4\xcf\x03\x06\x81\x80\xdao\x1d\xfd~\x87\xcd >_j\x95 \v\x90\x13\fNY8(\x1b\xf1\n\x943\x13\xe4V\x9d `\xba\x13\xa2\x1b\xe1\xe5\x03<\xf5\xe3\x93\x0f\b\xe4\x1a\xbf\x82\x9dHǫ\xbaޒ\f]\xa7}\xdbFGr\xaas\x03\xd1&\x8a\x0f\\\x1b<\xa0\xad\x99\xb6\x95\nzG\x82Zb\xc0ZuT\xe5@\\\xe9\x92ּ\f}\x9f\xf2\x83k\xe5\x94(\xc6\x12\xc8mG\x1b\xb9K\x9eQ\x9e\xd40\x855\x05\xaa\x84x_\x85\xb4\x94R\xf7\xe5\xff\xeb\xaf0xR*U\x8aroz\x96\x97\xa1>)\x9b\xe4\x1a\f\xe5\\\x13|\x9b1љΓ\x93\xfcG[B'\xc0qӒ$\x1a\xfc\x16\x91%\x95n\n{\x9d\x95\t6\b\xb13J\xd0L\r>8\xb8V-\xdak\xc5\xf8\x0f\xd7*U\x85\xabT\x84'Uk\xac\xb7S\xe3\x92\xdeq\xa3\xf62y\xa1\xb4\xf3\x8a\xb0\xeeP?h\xbc\x84B\r\xf5\n\xd1\xf80I\x90\x1a\xf4b\x1e\xefa>\xe7\x85\x02ʰhh;]\x05P\xc6\xe4Q\xa3\xec\xcdų\x8f$l&\xee\xeb|S\xe2p\xe3C\xf2\xe8@\x06C5\xc4\xd9{\x12C\x1f0\xa15gL\xbd\x98\xf3\x1cJ@\x93J\xac칣\x0f=\xb93̳R\x91+)\xbf\a\xc8\xcc\vm\xaf\xd5N\xd0\x19\x9cjO\xf6\xc6gz3\x1a8\x92\xecJ\xdf\xd8\xf1\xb0{Z\x15ҷ\xc7\xd3\xdc\xf2\xc4\xf7\xaf;L\x96E\x86\x11\x18u@I~0\xda\xd4\xe5\xa9i\x97\x00\x9f\"\xe7\xceS\xb3\x88\x90ԃ\xccpz\x8f\xa7\xf3DÏ\x8aۿ\x1b.\xb8ܨhe\x05/^\xfc8\xa43\xad\x1b\xbe4\x97\x87@\x036\x18Н͖\xe1\xfb\x9a\x15+\x91&1\f\x9b\x06\xb5\xd0\x01\xed)+\x14\x054W\xb0\x89\x02&b\xae\x9a\xd2\xfb\xa3\n\x86A\xfb\xb6SB\x1b\xb2$' \xbe\x80\xaf\xac\xf5G4}ű\xed䴄\x0f\x8eE9\x8d|7\x15S\xc6\n\x15\x94+V\xbdP\xe7\t\xaf\x02^\x84o=\vh\f\x89\x8e\xf6\x04\xc7\xe0\xdd\xf6b\xb0\x9f\xdf\x7f^\xc1;c\xc0\xcb\x0eC\"`\x13\xed\xd03\xa3\a\xc0U\x9e3W\x10\xc9\xfc\xef\x02\u058cЦ\x17cp(\x98\xb5\xd6x\xcdIf5vµ?`8\x10\x1e\xeb\xa3\x0f{r\xdb*\x05[\x95~\xe4:?\x03\xeb\x97\xf9\xe7Q\xdf\xdf\a\xdf\xc1\xb7\xd1\xd3t\xd5S\xe6[z\f\xb9\xc9\x1b\x16\x8cGv\xff\x12p\x88\x06H\xc6#a\x177K\xedۑ\xd3\x15Ӗ\xeb\x11vM\xcc\x11\xb9~\xf3\xf6\xbf\xff\xf9KD\xf7]\x91\xc2'\xf4\xe7:\xcb\xd9)E\x91K\x93\xb8\xbb.m\xe6\x03\xa4\x89\x99\xba\xb7\xed۳\b\xfe\x9c\xb2\f>m\xbc\xb7\xa8εd`\xf5\xb9KU\xba\xe19\xba\t\xf0\xbd\x1ae\xafU]U\xac\x95\xf8\x96\xf4\xc4z\x10\xee\x1fh\xecMo\x96\xba1\xe5`86\xf4sy\xde\xe6ǮڞM\xffG*2\x1fxuw\xc1\x93&\xb4(\x89\xfc\xfc\x19\x9d\x8f\xf5\x96\x9b~N\xeb\x18B~\x10\xe5\xcdI\x1c\xe9U\xfc\xf7\xcc\xe9n\xa7xFl\x9f\xe0\xf5M:9\x94\xc1R\x83\xfa\xa4-\x16@\xf0\xcd\f\xf7\x9e\xe5r\xfa\xd0\xc5v\x8e\x88\xef\x0e\x8a\xac\xda\xd8sի\xe0\x17\xa7.\xee^,\xfel=\xcf\x169\xbdg\xcd\n$Ăݳ\xac_\xf93\x00\x00\xff\xff\x1d6\xacA\x84\x0f\x00\x00"), diff --git a/pkg/apis/velero/v1/restore_types.go b/pkg/apis/velero/v1/restore_types.go index 377a92737c..783988e3a9 100644 --- a/pkg/apis/velero/v1/restore_types.go +++ b/pkg/apis/velero/v1/restore_types.go @@ -129,6 +129,13 @@ type RestoreSpec struct { // +optional // +nullable UploaderConfig *UploaderConfigForRestore `json:"uploaderConfig,omitempty"` + + // DisabledPVReprovisioningStorageClasses is a slice of StorageClasses names. + // PV without snaptshot and having one of these StorageClass will not be + // re-provisionned (even when ReclaimPolicy is Delete). + // +optional + // +nullable + DisabledPVReprovisioningStorageClasses []string `json:"disabledPVReprovisioningStorageClasses,omitempty"` } // UploaderConfigForRestore defines the configuration for the restore. diff --git a/pkg/apis/velero/v1/zz_generated.deepcopy.go b/pkg/apis/velero/v1/zz_generated.deepcopy.go index 03f98b4250..02f5efac46 100644 --- a/pkg/apis/velero/v1/zz_generated.deepcopy.go +++ b/pkg/apis/velero/v1/zz_generated.deepcopy.go @@ -1377,6 +1377,11 @@ func (in *RestoreSpec) DeepCopyInto(out *RestoreSpec) { *out = new(UploaderConfigForRestore) (*in).DeepCopyInto(*out) } + if in.DisabledPVReprovisioningStorageClasses != nil { + in, out := &in.DisabledPVReprovisioningStorageClasses, &out.DisabledPVReprovisioningStorageClasses + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreSpec. diff --git a/pkg/builder/restore_builder.go b/pkg/builder/restore_builder.go index bad4327e99..c3f27070ad 100644 --- a/pkg/builder/restore_builder.go +++ b/pkg/builder/restore_builder.go @@ -171,3 +171,9 @@ func (b *RestoreBuilder) ItemOperationTimeout(timeout time.Duration) *RestoreBui b.object.Spec.ItemOperationTimeout.Duration = timeout return b } + +// DisabledPVReprovisioningStorageClasses appends to the Restore's disabled PV re-rpovisioning StorageClasses. +func (b *RestoreBuilder) DisabledPVReprovisioningStorageClasses(storageClasses ...string) *RestoreBuilder { + b.object.Spec.DisabledPVReprovisioningStorageClasses = append(b.object.Spec.DisabledPVReprovisioningStorageClasses, storageClasses...) + return b +} diff --git a/pkg/cmd/cli/restore/create.go b/pkg/cmd/cli/restore/create.go index 17446f6983..4b321e50f7 100644 --- a/pkg/cmd/cli/restore/create.go +++ b/pkg/cmd/cli/restore/create.go @@ -78,31 +78,32 @@ func NewCreateCommand(f client.Factory, use string) *cobra.Command { } type CreateOptions struct { - BackupName string - ScheduleName string - RestoreName string - RestoreVolumes flag.OptionalBool - PreserveNodePorts flag.OptionalBool - Labels flag.Map - Annotations flag.Map - IncludeNamespaces flag.StringArray - ExcludeNamespaces flag.StringArray - ExistingResourcePolicy string - IncludeResources flag.StringArray - ExcludeResources flag.StringArray - StatusIncludeResources flag.StringArray - StatusExcludeResources flag.StringArray - NamespaceMappings flag.Map - Selector flag.LabelSelector - OrSelector flag.OrLabelSelector - IncludeClusterResources flag.OptionalBool - Wait bool - AllowPartiallyFailed flag.OptionalBool - ItemOperationTimeout time.Duration - ResourceModifierConfigMap string - WriteSparseFiles flag.OptionalBool - ParallelFilesDownload int - client kbclient.WithWatch + BackupName string + ScheduleName string + RestoreName string + RestoreVolumes flag.OptionalBool + PreserveNodePorts flag.OptionalBool + Labels flag.Map + Annotations flag.Map + IncludeNamespaces flag.StringArray + ExcludeNamespaces flag.StringArray + ExistingResourcePolicy string + IncludeResources flag.StringArray + ExcludeResources flag.StringArray + StatusIncludeResources flag.StringArray + StatusExcludeResources flag.StringArray + NamespaceMappings flag.Map + Selector flag.LabelSelector + OrSelector flag.OrLabelSelector + IncludeClusterResources flag.OptionalBool + Wait bool + AllowPartiallyFailed flag.OptionalBool + ItemOperationTimeout time.Duration + ResourceModifierConfigMap string + WriteSparseFiles flag.OptionalBool + ParallelFilesDownload int + client kbclient.WithWatch + DisabledPVReprovisioningStorageClasses flag.StringArray } func NewCreateOptions() *CreateOptions { @@ -158,6 +159,8 @@ func (o *CreateOptions) BindFlags(flags *pflag.FlagSet) { f.NoOptDefVal = cmd.TRUE flags.IntVar(&o.ParallelFilesDownload, "parallel-files-download", 0, "The number of restore operations to run in parallel. If set to 0, the default parallelism will be the number of CPUs for the node that node agent pod is running.") + + flags.Var(&o.DisabledPVReprovisioningStorageClasses, "disable-pv-reprovisioning-storageclasses", "PV with no snaptshot that has a StorageClass specified by this flag will not be re-provisionned.") } func (o *CreateOptions) Complete(args []string, f client.Factory) error { @@ -339,6 +342,7 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { WriteSparseFiles: o.WriteSparseFiles.Value, ParallelFilesDownload: o.ParallelFilesDownload, }, + DisabledPVReprovisioningStorageClasses: o.DisabledPVReprovisioningStorageClasses, }, } diff --git a/pkg/cmd/cli/restore/create_test.go b/pkg/cmd/cli/restore/create_test.go index 877de29d0c..645408243c 100644 --- a/pkg/cmd/cli/restore/create_test.go +++ b/pkg/cmd/cli/restore/create_test.go @@ -80,6 +80,7 @@ func TestCreateCommand(t *testing.T) { itemOperationTimeout := "10m0s" writeSparseFiles := "true" parallel := 2 + disabledPVReprovisioningStorageClasses := "storageclass1,storageclass2" flags := new(pflag.FlagSet) o := NewCreateOptions() o.BindFlags(flags) @@ -104,6 +105,7 @@ func TestCreateCommand(t *testing.T) { flags.Parse([]string{"--item-operation-timeout", itemOperationTimeout}) flags.Parse([]string{"--write-sparse-files", writeSparseFiles}) flags.Parse([]string{"--parallel-files-download", "2"}) + flags.Parse([]string{"--disable-pv-reprovisioning-storageclasses", disabledPVReprovisioningStorageClasses}) client := velerotest.NewFakeControllerRuntimeClient(t).(kbclient.WithWatch) f.On("Namespace").Return(mock.Anything) @@ -142,6 +144,7 @@ func TestCreateCommand(t *testing.T) { require.Equal(t, itemOperationTimeout, o.ItemOperationTimeout.String()) require.Equal(t, writeSparseFiles, o.WriteSparseFiles.String()) require.Equal(t, parallel, o.ParallelFilesDownload) + require.Equal(t, disabledPVReprovisioningStorageClasses, o.DisabledPVReprovisioningStorageClasses.String()) }) t.Run("create a restore from schedule", func(t *testing.T) { diff --git a/pkg/cmd/util/output/restore_describer.go b/pkg/cmd/util/output/restore_describer.go index 55363b4b63..3726e906c5 100644 --- a/pkg/cmd/util/output/restore_describer.go +++ b/pkg/cmd/util/output/restore_describer.go @@ -149,6 +149,13 @@ func DescribeRestore( d.Printf("\tCluster-scoped:\t%s\n", BoolPointerString(restore.Spec.IncludeClusterResources, "excluded", "included", "auto")) + d.Println() + s = emptyDisplay + if restore.Spec.DisabledPVReprovisioningStorageClasses != nil { + s = strings.Join(restore.Spec.IncludedNamespaces, ", ") + } + d.Printf("Disabled PV Re-provisioning StorageClasses:\t%s\n", s) + d.Println() d.DescribeMap("Namespace mappings", restore.Spec.NamespaceMapping) diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index 619db5b87e..445ef7c612 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -1235,7 +1235,19 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso // When the PV data is skipped from backup, it's BackupVolumeInfo BackupMethod // is not set, and it will fall into the default case. default: - if hasDeleteReclaimPolicy(obj.Object) { + hasDisabledStorageClass, err := hasDisabledPVReprovisioningStorageClass(obj, ctx) + if err != nil { + errs.Add(namespace, err) + return warnings, errs, itemExists + } + + if hasDisabledStorageClass { + obj, err = ctx.handleSkippedPVHasDisabledReprovisioningStorageClass(obj, restoreLogger) + if err != nil { + errs.Add(namespace, err) + return warnings, errs, itemExists + } + } else if hasDeleteReclaimPolicy(obj.Object) { restoreLogger.Infof("Dynamically re-provisioning persistent volume because it doesn't have a snapshot and its reclaim policy is Delete.") ctx.pvsToProvision.Insert(name) @@ -2527,3 +2539,36 @@ func (ctx *restoreContext) handleSkippedPVHasRetainPolicy( obj = resetVolumeBindingInfo(obj) return obj, nil } + +func hasDisabledPVReprovisioningStorageClass(unstructuredPV *unstructured.Unstructured, ctx *restoreContext) (bool, error) { + disabledStorageClasses := ctx.restore.Spec.DisabledPVReprovisioningStorageClasses + + // Converting Unstructured to PV object. + pv := new(v1.PersistentVolume) + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.Object, pv); err != nil { + return false, errors.Wrapf(err, "error converting persistent volume to structured") + } + + // Checking if PV StorageClass is in the DisabledPVReprovisioningStorageClasses list. + for _, disabledStorageClass := range disabledStorageClasses { + if disabledStorageClass == pv.Spec.StorageClassName { + return true, nil + } + } + return false, nil +} + +func (ctx *restoreContext) handleSkippedPVHasDisabledReprovisioningStorageClass( + obj *unstructured.Unstructured, + logger logrus.FieldLogger, +) (*unstructured.Unstructured, error) { + logger.Infof("Restoring persistent volume as-is because it doesn't have a snapshot and it's storage class has re-provisionning disabled.") + + // Check to see if the claimRef.namespace field needs to be remapped, and do so if necessary. + if _, err := remapClaimRefNS(ctx, obj); err != nil { + return nil, err + } + + obj = resetVolumeBindingInfo(obj) + return obj, nil +} diff --git a/pkg/restore/restore_test.go b/pkg/restore/restore_test.go index f3da852023..dd1b86480f 100644 --- a/pkg/restore/restore_test.go +++ b/pkg/restore/restore_test.go @@ -197,6 +197,27 @@ func TestRestorePVWithVolumeInfo(t *testing.T) { test.PVs(): {}, }, }, + { + name: "Restore PV with ClaimPolicy as Delete and Disabled Re-provisioning", + restore: defaultRestore().DisabledPVReprovisioningStorageClasses("no-reprovisioning").Result(), + backup: defaultBackup().Result(), + tarball: test.NewTarWriter(t). + AddItems("persistentvolumes", + builder.ForPersistentVolume("pv-1").StorageClass("no-reprovisioning").ReclaimPolicy(corev1api.PersistentVolumeReclaimDelete).Result(), + ).Done(), + apiResources: []*test.APIResource{ + test.PVs(), + }, + volumeInfoMap: map[string]volume.BackupVolumeInfo{ + "pv-1": { + PVName: "pv-1", + Skipped: true, + }, + }, + want: map[*test.APIResource][]string{ + test.PVs(): {"/pv-1"}, + }, + }, { name: "Restore PV with ClaimPolicy as Retain", restore: defaultRestore().Result(), @@ -2464,6 +2485,7 @@ func TestRestorePersistentVolumes(t *testing.T) { wantError bool wantWarning bool csiFeatureVerifierErr string + volumeInfoMap map[string]volume.BackupVolumeInfo }{ { name: "when a PV with a reclaim policy of delete has no snapshot and does not exist in-cluster, it does not get restored, and its PVC gets reset for dynamic provisioning", @@ -3190,6 +3212,172 @@ func TestRestorePersistentVolumes(t *testing.T) { })).Result(), want: []*test.APIResource{}, }, + { + name: "when a PV with a reclaim policy of delete has no snapshot does not exist in-cluster and has a StorageClass that disable re-provisioning, it gets restored, with its claim ref", + restore: defaultRestore().DisabledPVReprovisioningStorageClasses("no-reprovisioning").Result(), + backup: defaultBackup().Result(), + tarball: test.NewTarWriter(t). + AddItems("persistentvolumes", + builder.ForPersistentVolume("pv-1"). + StorageClass("no-reprovisioning"). + ReclaimPolicy(corev1api.PersistentVolumeReclaimDelete). + ClaimRef("ns-1", "pvc-1"). + Result(), + ). + AddItems("persistentvolumeclaims", + builder.ForPersistentVolumeClaim("ns-1", "pvc-1"). + VolumeName("pv-1"). + ObjectMeta( + builder.WithAnnotations("pv.kubernetes.io/bind-completed", "true", "pv.kubernetes.io/bound-by-controller", "true", "foo", "bar"), + ). + Result(), + ). + Done(), + volumeInfoMap: map[string]volume.BackupVolumeInfo{ + "pv-1": { + PVName: "pv-1", + Skipped: true, + }, + }, + apiResources: []*test.APIResource{ + test.PVs(), + test.PVCs(), + }, + want: []*test.APIResource{ + test.PVs( + builder.ForPersistentVolume("pv-1"). + StorageClass("no-reprovisioning"). + ReclaimPolicy(corev1api.PersistentVolumeReclaimDelete). + ObjectMeta( + builder.WithLabels("velero.io/backup-name", "backup-1", "velero.io/restore-name", "restore-1"), + ). + ClaimRef("ns-1", "pvc-1"). + Result(), + ), + test.PVCs( + builder.ForPersistentVolumeClaim("ns-1", "pvc-1"). + VolumeName("pv-1"). + ObjectMeta( + builder.WithLabels("velero.io/backup-name", "backup-1", "velero.io/restore-name", "restore-1"), + builder.WithAnnotations("foo", "bar"), + ). + Result(), + ), + }, + }, + { + name: "when a PV with a reclaim policy of retain has no snapshot does not exist in-cluster and has a StorageClass that disable re-provisioning, it gets restored, with its claim ref", + restore: defaultRestore().DisabledPVReprovisioningStorageClasses("no-reprovisioning").Result(), + backup: defaultBackup().Result(), + tarball: test.NewTarWriter(t). + AddItems("persistentvolumes", + builder.ForPersistentVolume("pv-1"). + StorageClass("no-reprovisioning"). + ReclaimPolicy(corev1api.PersistentVolumeReclaimRetain). + ClaimRef("ns-1", "pvc-1"). + Result(), + ). + AddItems("persistentvolumeclaims", + builder.ForPersistentVolumeClaim("ns-1", "pvc-1"). + VolumeName("pv-1"). + ObjectMeta( + builder.WithAnnotations("pv.kubernetes.io/bind-completed", "true", "pv.kubernetes.io/bound-by-controller", "true", "foo", "bar"), + ). + Result(), + ). + Done(), + volumeInfoMap: map[string]volume.BackupVolumeInfo{ + "pv-1": { + PVName: "pv-1", + Skipped: true, + }, + }, + apiResources: []*test.APIResource{ + test.PVs(), + test.PVCs(), + }, + want: []*test.APIResource{ + test.PVs( + builder.ForPersistentVolume("pv-1"). + StorageClass("no-reprovisioning"). + ReclaimPolicy(corev1api.PersistentVolumeReclaimRetain). + ObjectMeta( + builder.WithLabels("velero.io/backup-name", "backup-1", "velero.io/restore-name", "restore-1"), + ). + ClaimRef("ns-1", "pvc-1"). + Result(), + ), + test.PVCs( + builder.ForPersistentVolumeClaim("ns-1", "pvc-1"). + VolumeName("pv-1"). + ObjectMeta( + builder.WithLabels("velero.io/backup-name", "backup-1", "velero.io/restore-name", "restore-1"), + builder.WithAnnotations("foo", "bar"), + ). + Result(), + ), + }, + }, + { + name: "when a PV with a reclaim policy of delete has a snapshot does not exist in-cluster and has a StorageClass that disable re-provisioning, the snapshot and PV are restored", + restore: defaultRestore().DisabledPVReprovisioningStorageClasses("no-reprovisioning").Result(), + backup: defaultBackup().Result(), + tarball: test.NewTarWriter(t). + AddItems("persistentvolumes", + builder.ForPersistentVolume("pv-1"). + StorageClass("no-reprovisioning"). + ReclaimPolicy(corev1api.PersistentVolumeReclaimDelete). + AWSEBSVolumeID("old-volume"). + Result(), + ). + Done(), + apiResources: []*test.APIResource{ + test.PVs(), + test.PVCs(), + }, + volumeSnapshots: []*volume.Snapshot{ + { + Spec: volume.SnapshotSpec{ + BackupName: "backup-1", + Location: "default", + PersistentVolumeName: "pv-1", + }, + Status: volume.SnapshotStatus{ + Phase: volume.SnapshotPhaseCompleted, + ProviderSnapshotID: "snapshot-1", + }, + }, + }, + volumeSnapshotLocations: []*velerov1api.VolumeSnapshotLocation{ + builder.ForVolumeSnapshotLocation(velerov1api.DefaultNamespace, "default").Provider("provider-1").Result(), + }, + volumeSnapshotterGetter: map[string]vsv1.VolumeSnapshotter{ + "provider-1": &volumeSnapshotter{ + snapshotVolumes: map[string]string{"snapshot-1": "new-volume"}, + }, + }, + volumeInfoMap: map[string]volume.BackupVolumeInfo{ + "pv-1": { + BackupMethod: volume.NativeSnapshot, + PVName: "pv-1", + NativeSnapshotInfo: &volume.NativeSnapshotInfo{ + SnapshotHandle: "testSnapshotHandle", + }, + }, + }, + want: []*test.APIResource{ + test.PVs( + builder.ForPersistentVolume("pv-1"). + StorageClass("no-reprovisioning"). + ReclaimPolicy(corev1api.PersistentVolumeReclaimDelete). + AWSEBSVolumeID("new-volume"). + ObjectMeta( + builder.WithLabels("velero.io/backup-name", "backup-1", "velero.io/restore-name", "restore-1"), + ). + Result(), + ), + }, + }, } for _, tc := range tests { @@ -3233,6 +3421,7 @@ func TestRestorePersistentVolumes(t *testing.T) { BackupReader: tc.tarball, CSIVolumeSnapshots: tc.csiVolumeSnapshots, RestoreVolumeInfoTracker: volume.NewRestoreVolInfoTracker(tc.restore, h.log, test.NewFakeControllerRuntimeClient(t)), + BackupVolumeInfoMap: tc.volumeInfoMap, } warnings, errs := h.restorer.Restore( data, From 96d3ff232bf1a7528f96eb3dd112e68b9093275c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Rostagni?= Date: Fri, 11 Oct 2024 10:11:07 +0200 Subject: [PATCH 2/2] Add PR changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Clément Rostagni --- changelogs/unreleased/8287-clcondorcet | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/8287-clcondorcet diff --git a/changelogs/unreleased/8287-clcondorcet b/changelogs/unreleased/8287-clcondorcet new file mode 100644 index 0000000000..c7f31a9ce9 --- /dev/null +++ b/changelogs/unreleased/8287-clcondorcet @@ -0,0 +1 @@ +Add disabled PV re-provisioning by StorageClasses option on restore