From 2197cab3dbf1038b7afe363284d7b9e18c9300dc Mon Sep 17 00:00:00 2001 From: Daniel Jiang Date: Tue, 16 Apr 2024 16:39:43 +0800 Subject: [PATCH] Display CSI snapshot restores in restore describe This commit makes change to CLI so `velero restore describe` will download restore volume info and render the CSI snapshot restores based on its content. Signed-off-by: Daniel Jiang --- changelogs/unreleased/7687-reasonerjt | 1 + .../v1/bases/velero.io_downloadrequests.yaml | 1 + config/crd/v1/crds/crds.go | 2 +- pkg/apis/velero/v1/download_request_types.go | 2 +- pkg/cmd/util/output/restore_describer.go | 62 +++++++ pkg/cmd/util/output/restore_describer_test.go | 152 ++++++++++++++++++ pkg/controller/download_request_controller.go | 3 +- 7 files changed, 220 insertions(+), 3 deletions(-) create mode 100644 changelogs/unreleased/7687-reasonerjt diff --git a/changelogs/unreleased/7687-reasonerjt b/changelogs/unreleased/7687-reasonerjt new file mode 100644 index 0000000000..38f13fae2b --- /dev/null +++ b/changelogs/unreleased/7687-reasonerjt @@ -0,0 +1 @@ +Display CSI snapshot restores in restore describe \ No newline at end of file diff --git a/config/crd/v1/bases/velero.io_downloadrequests.yaml b/config/crd/v1/bases/velero.io_downloadrequests.yaml index 457a3a1551..03644a56bb 100644 --- a/config/crd/v1/bases/velero.io_downloadrequests.yaml +++ b/config/crd/v1/bases/velero.io_downloadrequests.yaml @@ -60,6 +60,7 @@ spec: - CSIBackupVolumeSnapshots - CSIBackupVolumeSnapshotContents - BackupVolumeInfos + - RestoreVolumeInfo type: string name: description: Name is the name of the Kubernetes resource with diff --git a/config/crd/v1/crds/crds.go b/config/crd/v1/crds/crds.go index 12177218cb..8722e36865 100644 --- a/config/crd/v1/crds/crds.go +++ b/config/crd/v1/crds/crds.go @@ -33,7 +33,7 @@ var rawCRDs = [][]byte{ []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec}_s\xdb8\x92\xf8{>\x05ʿ\x87\xd9ݒ\xecI\xfd\xf6\xe1\xcao\x19'\xb9Q\xedL\xe2\x8a=\xd9g\x88lI\x18\x83\x00\x17\x00ek\xef\xee\xbb_\xa1\x01\xf0\x8f\b\x92\xa0,{\xb2{\xe1Kb\x11l\x00ݍ\xeeFw\xa3\xb1\\.\xdfВ}\x05\xa5\x99\x14ׄ\x96\f\x9e\f\b\xfb\x97\xbe|\xf8\x0f}\xc9\xe4\xd5\xfe\xed\x9b\a&\xf2krSi#\x8b/\xa0e\xa52x\x0f\x1b&\x98aR\xbc)\xc0М\x1az\xfd\x86\x10*\x844\xd4\xfe\xacퟄdR\x18%9\a\xb5܂\xb8|\xa8ְ\xae\x18\xcfA!\xf0\xd0\xf5\xfe\xc7˷\x7f\xbd\xfc\xf1\r!\x82\x16pM\xd64{\xa8J}\xb9\a\x0eJ^2\xf9F\x97\x90Y\x90[%\xab\xf2\x9a4/\xdc'\xbe;7ԟ\xf0k\xfc\x813m\xfe\xd6\xfa\xf1\x17\xa6\r\xbe(y\xa5(\xaf{\xc2\xdf4\x13ۊS\x15~}C\x88\xced\t\xd7\xe4\x93\xed\xa2\xa4\x19\xe4o\b\xf1\xa3\xc6.\x97~\xc0\xfb\xb7\x0eB\xb6\x83\x82\xba\xb1\x10\"K\x10\xefnW_\xff\xff]\xe7gBrЙb\xa5\xc1\xb9\xff\xf7\xb2\xfe\x9d\xf8Q\x12\xa6\t%_q\x8eDy\x94\x13\xb3\xa3\x86((\x15h\x10F\x13\xb3\x03\x92\xd1\xd2T\n\x88ܐ\xbfUkP\x02\f\xe8\x16\xbc\x8cWڀ\"\xdaP\x03\x84\x1aBI)\x990\x84\tbX\x01\xe4O\xefnWD\xae\x7f\x87\xcchBEN\xa8\xd62c\xd4@N\xf6\x92W\x05\xb8o\xff|YC-\x95,A\x19\x16\x90\xee\x9e\x16'\xb5~\x1d\x9b\xab},z\xdcW$\xb7,\x05nZ\x1eŐ{\x8c\xda\xf9\x99\x1d\xd3\xcd\xf4\x91\xc9\xec\xcfT\xf8\xe1_\x1e\x81\xbe\x03e\xc1\x10\xbd\x93\x15\xcf-'\xeeAY\x04fr+\xd8?kؚ\x18\x89\x9drj@[\xcc\x18P\x82r\xb2\xa7\xbc\x82\x85E\xca\x11\xe4\x82\x1e\x88\x02\xdb'\xa9D\v\x1e~\xa0\x8f\xc7\xf1\xabT@\x98\xd8\xc8k\xb23\xa6\xd4\xd7WW[f\xc2\xfa\xcadQT\x82\x99\xc3\x15.\x15\xb6\xae\x8cT\xfa*\x87=\xf0+ͶK\xaa\xb2\x1d3\x90Y2_ђ-q\"\x02\xd7\xd8e\x91\xff\xbf\xc0\x1e\xbaӭ9X\xb6\xd5F1\xb1m\xbd\xc0\xf51\x83\xe7\f\x84!\xbaZ\x17\xccX6\xf8G\x05ڮ\x01y\f\xf6\x06e\x10Y\x03\xa9\xcaܲ\xf1q\x83\x95 7\xb4\x00~C5\xbc2\xad,U\xf4\xd2\x12!\x89Zm\xc9z\xdcء\xb7\xf5\"\b\xc8\x01\xd2:\xc1rWB\xd6Yh\xf6+\xb6a\x99[N\x1b\xa9\x1a\xb9\xe3d`\x17C\xf1\xa5o\x9fL\xb3;AK\xbd\x93\xe6\x9e\x15 +s\xdcb\x8aאxw\xab#(a\x84~\xbc(\xb3*\r\xb9]\xb4\x8f\x94\x19\x1c\xf3\xcd݊|Ea\x15\xbeF\xa1Uib*%,\x97D\xfa\xfa\x024?\xdc\xcb\xdf4\x90\xbcB\xe6\xce\x14 \x1e\x16d\r\x1b\xcb\t\n\xec\xf7\xf6\x15(eq\xa3q\x00\xb2\xea\t\x1b\xfb\xdc\xef\xc0\xe2\x96V\xdc\xf8u\xc24y\xfb#)\x98\xa8L\x8f\xd5\x06\xa9\x8e\x98\xa2\x86\x16r\x0f\xea\x14$\xbe\xa7\x86\xfej?>\u009d\x05J\x10\xaaE\xde\xda\xe3q}\xc0\x971j\xbbg\xb5iAd\x9a\\\\\x10\xa9ȅ\xd3\xc0\x17\v\xf7uŸY2\xd1\xee\xe3\x91q\x1ez\x997y\x87CGP}/?jǼ'\xe1b\x00V\v5\x8f;0;P\xa4\x94\xb5\xc6\xdb0\x0eD\x1f\xb4\x81\xc2#&h\x11?\x9fHO\xb8v8\xf7 \xb4ū\x9fH\x7f\xf2\xa2✮9\\\x13\xa3*\x18\xc0\xcdZJ\x0eTL \xe7\vhòs\xa0\xc6A\x8a F\xf9\x17\x1d\f\xa0Ҥ\x0f@h\x04\xb4Ǚ\xd5Μ\xb7\x10\xdb\xc5ʛ\xe8\xa0J\x05\x99\x15\xdb\xd7^\x1d0ਂ\x84$\\\x8a-(\u05fd5U\x02\x87)\xb0\x1c\x97\x13+i\x15p\xabNȦ\xb2B\xf8\x92\xd8\xe5=\xc8\x04Lh\x034\u009d\xcf \x10\x8cB\xf4꙳\f\xad@o\xf0-\xd1p\x8d\xf1i\xa3\xa5\x0f%8\xdb\xd9\xd2\xd2\x0f\xbbQ\xbf\xa3\x02A\x83\xb1\x1f]\xfc\xe5b\x81$\xee\xf6\xda\xedC\x13\xaa\xa0FK\xb2\xe0\x84\xa24\x87~kf\xa0\x88`qT\xa0$ғ*E\x0f\x03Ԭ7\x00g\xa4\xe7\x10\xcc#\x8a\x8a\xd0\xec\x95iz\xdc\xef\xbf3U\xcfCG\x8d\xdb]ʄ\xa5\x9f\xddyvȧ\xdd\x06\u03a2MH\x13\x81DŽ\x83\x87{\xb3\x11j\xfdA\xc8:\v\xcf\x0f1y\xcd[\x9ey\xff%1\xb5\x93\xf2a\n;?\xdb6ͮ\x88d\xe8V!k\xd8\xd1=\x93\xcaO\xbdѵ\xf0\x04Ye\xa2\xab\x9e\x1a\x92\xb3\xcd\x06\x94\x85S\xee\xa8\x06\xed\xf6\xc9\xc3\b\x19\xb6\xdfIK\x8cD_\x1eͣ!\xa4%\x13\xce|h\xe8\u05908֒\xe1\xb1\x03\xb5\xf65*\xe3\x9c\xedY^Q\x8ez\x99\x8a\xcc͇\xd6\xe3\x8aI\x99\x11\"\xf7\xc6\x1c\xe5L\xf78\x83 L\xca\x12\xa9\xb3U\x92\x02\xac\xd1[\xd8MA\xbf\xe9\xf0\xcc\xd7\xd4\xda*rh\xf6\x04\x89\xa5*\x0e\xdaw\x95\xa3\x1d\xd9ȌEC\x14\xf4D\x10N\xd7\xc0\x89\x06\x0e\x99\x91*\x8e\x91):\xbb'E\b\x0e 2\"\xf9\xba[\x8df\x02# \t\xee\xe1v,\xdb9S\xcf2\x11\xc2!\xb9\x04k\xf0\x19B˒G\xd4E\xf3\x8c\x12\xdfw2\xb6֛gb\xd5\x1fË\xad\xff\xe6I\x90\x99\xcd\x13Em\xb3\xbe\xba\x98\xad\xd9!\xbe\xa9m\x9e\x7fO\xc4\x06\xc9\x7f\x02ӎ\xac~\x82n\xa1d\x9e\x1e\xe4[\x8bU\x06\xfaҚSh\xe9,\b3\xe1ש\x95б\xb9z\u07b2\x0e\x12\xbem\xda\xccg\xfaDҤ\xac\x89\x17\"L\xddſ ]Pe\xdcy\x8d\x91L\x93_\xda_-\b\xdb\xd4H\xcf\x17dø\x01u\x84\xfd\x93D}\xa0\xcc9\x90\x91\xa2\xf5\b\xfa\xefM\xb6\xfb\xf0dM0݄\xaa\x12\xf1r\xfc\xb13d\x83\xb5\xdfU\xcf\x13p\t\xfa\xb1\x99\x82\x02\xfd\xe3\xb8cj\xff\x82\xa6ջO\xef\xe3\xfb\xab\xf6\x93\xc0y\xbd\x89L,:\xf7\xbc;\x9aQ{|ބ\x0fo\xd0\x06\xaa7@.\x16\xb2 \x94<\xc0\xc1\x99.T\x10K\x1f\x1a\x1a't\xaf\x00\x832\xc8g\x0fp@0\xf1(K\xffI\xe5\x06\xf7<\xc0!\xa5\xd9\x11\x0e혘\xf6\xd1#\x8b'\xfb\x03\"\x02\x9d\xeb\xa9l\xe0\x1e\xbf\x14\"1\x8d\xf8\x93(K\xc2\x13p\x7f\xc24\x93X\xa5\xddG;L\x89\x1c\xf0\x83v\xb4\xb4+f\xc7J\x14\xab\xe8q\x90\x9bd\x82\xba\xe7+\xe5,\xaf;rkd%\x16\xe4\x934\xf6\x9f\x0fOL\xfbH\xe6{\t\xfa\x934\xf8ˋ`\xd4\r\xfc%\xf1\xe9z\xc0\x85&\x9c\x94\xb7\bk\xc7\xe2\x9cN\xb3\xdcV\xe3\x9ei\xb2\x12v\xbb\xe2P\x92\xd8\x15\x86]]w\xae\xa3\xa2\xd2\x18F\x13R,\x9d\xdb&֓ǷT\x1dt?\xbbS\xdf\xe1\xbdU\x16\xee\x8d\v\xfer\x9aA\x1e\xe25\x18\x95\xa4\x06\xb6,K\xec\xaf\x00\xb5\x05RZ\x11\x9e\xc6\x11\x89\x82\xd5\xcff\x1e\xfb\xa4i\xef\xf0x\xc1\x9bO\x0ffi\x17\\B\xab@\xc6ɦ\x03\x11\xc7\xe1\xa6\xd33B-\x8a&\xc6$vi\x9ec\xa2\t\xe5\xb73$\xfa\fZ\xcc]\x9a\xad\xb1;\x15XP\x8cu\xfc\x97\xd5t\xc8\xcd\xffCJʔ\xbe$\xef0\xa7\x84C\xe7\x9dwZ\xb5\xc0$t\x899!\x96\x05\xf6\x94[\xddk\x05\xa8 \xc0\x9d&\x96\x9b\x9e]\xb2 \x8f;\xa9\x9dڬ\x83(\x17\x0fpp!\xbb\xc9.ۋ\xfcb%.\x9c\x0e\xef-\xd8Z\xe1K\xc1\x0f\xe4\x02\xdf]<ǔId\xb6\xc4fOˇ:-fY\xd0r\xe9\x19\xd4\xc8bDh`NO\xaa\xa1l7\x8c\xc1\b\xb0\x1fֹ*\xd6\xc8\x1d\x9bm\x12\x8b\x96RG\"\xe9\x03C\x99`\xde[\xa9\x8d\xf3Wul֨CK\x06'\x16\xa1\x1b\x97@$U\xc8\xf6\xb0Bq\xca\xf5\xda~\xeew\xa0\xc1\xc7\v\xbcc\xcc\x01\xb5;\xab\x8bf};i{\xe1\xe2\x15\xd8\t\xcd\xd0b\xc0oK%3\xd0\xd1`r\xf3$\xc8\xebHZD{\xee\xb5Ϗ\xba]\x8aˉ\x18wA\x86'\xdd䴈\x98i\xaf\x7fxj9$\xedڷ\x7fO\xf1\xd8\xdcq\x11\xcc\xd9+\nz\x9c'\x944\xc4\x1b\xf7eX\r\x1e\x903\xfeնBI\x90\xaaKk\x06\xfc\x16\x14u\xc1\xc4\n; oϮ\xd8I\x90\xa1\xb1l\x8f\xd8s\x9a)y\x13:i\xa8S\xff\xe0\x96r)\xd1U\xaf\xa0C\xbc\xbeW\x1b\xed@!M\xcb!0\xc3\xdc+e\xfe\x83&\x1b\xa6\xb4i\x0fA\x0f\xe4\x89D\xc1\xcc\xdc\xf8\x88\x0fJ\x9d\xb4\xef\xf9\xec\xbel\xb9\x9bv\xf21\xe4G9\xc4$\xce\x1c\xe3;@؆0C@d\xb2\x12\xe8@\xb1\xeb\x18\xbbp\xc8u\x12\x96\xa5.\x92\xb4\xd5o\x1f\x10U\x91\x86\x80%r\n\x13\xa3\x9e\x96v\xf3\x8f\x94\xf1\x97 \x9b\x19J#\x8b=\xa7\xad\x89\x90c\xd6Έ+\xe8\x13+\xaa\x82\xd0\xc2\xd2\b\x959+\xa0K\xf4&\xf3\xcc~\x81j\xc2H\xbbbJ\x0e\x06|\xf6X\xe2\x182)4ˡV\xae\x9e\x11\xa4 \x94l(\xe3\x95J\x94\x80\xb3\xd0;g7\xe1%\xc1\xf9\xb6\ti\x9d/\x11\x15\t\xde\xd4D[q\\\x1a\x97*\xdd\xe2\x9b2\xb3\x14̷\xb2J\xc5$\xe6\xe5\x9d\xd9\xd0\xf2\x99\x8cT\x1c\xbe[Z\xa9C\xfdni\x8d=\xdf-\xad\x89绥\xf5\xdd\xd2Ji\xf9\xdd\xd2\xfani\xb5\x9f\xff\x13\x96\xd6Ԉ܁\xba\x81\x97\x93\xa3H\b\x15\x8f\rq\x04\xbeOn\xf09\xd8\xcfʅ\\\xc5AE2\xef\aҪcB\xabQ\x1eur\xa4]5\x81\xe7\xdd\xf9\x9e\tS\xf2\x19Y\xef\xa1\xd3\xf3e\xbd\xafF!\x9e)\xeb\xdd\x0f{\xda\xc6>)\xe7= e^v\xf4\xc2'J\x14@\x83[݅\xc1c\xf3\x1a␉\xfe_91\xb6\x97\xb5uF\xfex\xf1,\xfad\x1e\x89\x92\xf4\xe2/\x17\xdf\x1e\xfaσ\xf0A\x14\xf7q\xe7\x0f\x18G\xa0\xda\x1dh;-\xab\x9b\x05\xf7m\xb2\xf1Y\xf865\x13\xbeFb\x04V\x97%\x8f\xb0\xf8\xad\xca\x02\x03\xc5\xe7\xd2k\xa4g\x1c\x15]E\xe0$\x1d\x16\xa5\xfa \xb2\x9d\x92BV\xda{%,\xacw\x99;Q\x1e@Ƙ5\xba\xc2\xffJv\xb2\x8adb\x8f\xa0o\"#oz\xf2\x9d\xe4<\x1f\x84\x06C\xf7o/\xbbo\x8c\xf4\xa9z䑙]\x04\xd0\xe3\x0e\x04F\xd8Ŷ\x9d\x80\x1f\n\x02\xf8\x93\xf1\xc7\f\x16\x01$\x15\x11\x8c;Ϋ\xcb\t\xb4\xf9\x8e|.\x9d\xefi\xb6\xdd1\xeeSIK\xe6;9\x85\xaf\x9b\xa27`\x97\u038dv\x9f\xe5\xc8\xc2\x1f\x92\x9a7?!/\xc5#6\x91|wB\xca]bn\xef\xb3\xc3\xf3)Iusv\xcc/\x96@w\xfe\xb4\xb9$\xfcL\xa7\xc8\xcd\xc1\u038b\xa7ýb\x12\xdc뤾%&\xbc\x9d/s\xfd\x1c\x1e\x80\xe1\xf4\xb5ɤ\xb5I\x0f\xc1\xf8\xf8&\xd3\xd2\xe6$\xa3Mb,\x8d\xf5_-\xdd\xecՒ\xcc^7\xb5l\x94%F_\xceI\x1e\x8b\xd7j!\x93\n\x90\xbf\x16\xb3\x9d\x8a\x06\xa9:&\xe5I{\x9e\xcfG0,ჹ\xf5JvkQq\xc3J\x8e\xc1\xcd=ˣ\x0e\x00\xb3\x83C]T\xe2w\x89\xc71}y\x94\xcf_j\xae\xbd<\xb2\xbe\xa9&\x8f\xc09\xa1\xb1u՛y\xe6\xca\x13er\tVG\xd8\xd5\xe9\xabe\xf8\x9aF\v\xc7\xeex\xe2\x145M\x11s\xfbP1\\ZeP\x98\xa7ț\x9eU\xe9lc\xfc\xed\x1f\x15\xa8\x03\xc1\xe2.\xb5\xed\xd1\x1c\x8c\xf2\vS\xdb\xcdQ\x10\x15^l\r\xf9\xb4{\x86x\xb3\x94\xc9;\xe14\xe1\xf1x\xf0\x1b+#\x9a\x8d\x86\x15|v\x0f\x11\xedc\xe0s!\xeb\xaf#\x9fM\x19\xad\xa9'\x88^v\xdb1\x7f\xe31\xa9\xe9ӭ\xb1?\xe8d\xd0)'\x82҂\xf2\x93'\x80^j\x1b2\xb5\x11I\xb6\xbd\xd2N\xf8\xcc\v\xe0\xbd\xe0\x89\x9e\x978ɓ\x88\xa9\x94\x93;\xf3\xf0\xf4\n'u^\xf5\x84\xcek\x9d\xccI>\x91\x93\x94v\x92\x1c\x99MI\x1b\x99\x0e\x9e\x8e\x9f\xb4I8a\x93\x10V\x9d\x1ai\xc2I\x9ay'h\x12p\x98\xba4^\xf1\xa4\xcc+\x9e\x90y\xed\x931\x13L2\xf1z\xde\t\x98\x93\xdd\xfaR\xe5\xa0FC#\xa9\\8\xca\x7f){\x8d\xee@\x8eb\x02\xa14\x9dmձ_Q\\\xfbj\x98X\xf7t(\xc4g9\xad\xa5\xfd;\xf1\x9a\xc6\x1c\xe9\x1aw\xbe\x18\xaa\v\xe9h(\xa9\xc2\x02\xbb\xeb\x83K\xf9\x88\xaa\xca\x0f4\xdb\x1dA\xdfQM6R\x15Ԑ\x8b:Hv\xe5\x80ۿ/.\t\xf9(뼁v\xed\x18͊\x92\x1f쎁\\\xb4?8\x8d\x03\xa2\xdc\x16z\xbb\x95\x9ce\x11[*Z?\xc85\xee\x15t\xc0\xaaFY;\xac^چqS\nͮn\x9dƍ\xe4\\>\xce܋Ӓ\xfd'\x96\x97~\x86\xb7\xe6\xdd\xed\na\x04\xf6\xc0z\xd5u\x02S=\x9b5X5\xd9\xccsh\xed\xaf6\x1d\x88\xdd\\\xc0v\x05W\xc8]\xb1ޠ\xa6\xbd\xe8̤\x95.\xb7+7\x8e\xa1^,\xcfPq \x12\xb3N̎\xa9|YRe\x0e.\x99a\xd1\x19CP\x8bcޖA\xed\xd1/@\x1cEo\xa8;\x8cQ\xbcC\xd9\r\x8c\x1e\xe3\xee\x94q\f\x9f\xf0\x9b<\xdbw\xc6q\f[\x18K\xc4T\xe4\xe7hv\xd4ټXڗ\xcf\xfdU\xee\xe1}ԛ\xd5A\xcf\xddQ\xf3H\nS\x80\xe8*\xc3\x0efr\xae\x01\xab\xc6\xf6_=#')t\xed\xeb~\x9e⸺낈\xcc/\x94A\r\x9d\xc5\xe4\x13V)?\x90ۯ\xb8g\xaaE\x9b_\xa2~\xcf\x14\\W!`\x1a\x81\xe3?\xf8\xe9\xfc\xe9[\xdaHE\xb7\xf0\x8bt\x85\xa0\xa7\xc8\xdem\xdd)\x10\ueb5e\x90c\x19\x16M\xacJ\xac/I}\x04\xacɋ\xeeU\u07b5\xa3\x9cYK\xd8\x18~\n\xdd\xef\xef\x7fq\xb32\xac\x80\xcb\xf7\x95K\t\xb02Q\x83Eq\x98\xad\x83\xb4\xb6\xff\xdd\xc9G,P\x1b\xf7+\x86\xc2\xfe\xcdd\x14`B6\xa6\xe9͚RUrIsP7Rl\xd8vbv\xbfu\x1a\x1f\xa9\xd9\f\x7f\xf4\x93\xabuT\x80\x7f\xe68\xbd\xb5y8\a\xfe\x91q\xd0nX\t\x02\xf8\xb6\xffU-\x8f\xabb\xedl\xb8\x8d}Yw0\xa0\xe3ܴ\xd05\\\x82\xb2V\x94s\"W:\xf0\xea\xf0\xc4\x1b\x8a0a`\v\xfd\r݈\x04\xdew\n\x93\a>\x9f\x12G_\xe3_\xb5\xcc\xca\xd6Jsv\xa5\xdcD\x06>\x04\xa7u\xcd\xc3#3\xbe,\xd3y\xebh\x0em\x16\x86\n\xd8c\xc5\xf6\xe9\x12\xf6\xae\xb0\xbb\xbf\xf8\xc23r\xa5\xb0\b\xa6/\xfa\x8eE#O\xaab\xbf\xaeӁ\xea\xd4\"\xfd\xce\x18(J\x13\xd3\xd2ӂ\xe4\xa71\x80\xb5\x85#\r\xe5-~\xa6\xa1A\xccF\xd5\a\x91\x8d\xa5-\xf9uT8h\x83\x8c`\xa77\nir\xc2>\x99\x18D\x1eVz8\b3\x0f\x15\x9e\n>\xd7N\x1bZ\x9cT\x8f\xff\xa6\x0f\x06odQy+e\x8f\xd6c\xa7\xba!\x7fL,7\xe0ܗ\xb8=\xb1\xd0 '\xb0\aA\xac^s(\x0eW\n̈́\xe2\xcfO:\xdd\x104Ep\"D\xef\x9d!\xdeO\xa0\xf1~\x93\x1ft\r\x133\x11\xf1\xba\x8a>\x12\xfaf\xa3\xdb\xe7_[\xbb\x19\x96\x16\xc4i\xf6^T6g\x9au\xf5\xc2\xf3\x84\xdc\xcd\xddj\b\xdc)\"\xae\x7f\x9b\xc73\x97q\x7f\xba\xcf\x12i\xfd\xe9\xce\x12h\x11\x885\x8f\x9f\x7f\xee\xb8\xd4O+ٍ_:\x83#\v'\xb4(\xe7\xfe\x18]\x01Z\xd3m\xa8\xd5\xfdh\x8d\xf6-\bp\x8e-\x17\x06\x88\x00m\xce\\u+U\xbb%C3SQ\xdfAH\x1fm\xb5\xfaA\x13.cP\xf1\xbe\x0e\x16.\x82\n\xbb\x99\x99\x88z*\x99J\xd9\xfd|\xa8\x1bZܠ\r\x89\xd4i\xae\xee\x02ζ\xcc\xee\x12,\xe5\xb6T\xad\xe9\x16\x96\x99\xe4\x1cPZ\xf7\xc7\xf5\x92kݟl\xfb\x02TON\xedc\xbb\xad\x8fe9j\xbb\x10.u\xc9\xd4x9\x93a\n\x9a{\xd2z\x03\x92\xd8\U0006c34d\xc3B\xf4\x12\xb1\xfeH\xdbmê\xf3b\xd9{H\xfd\x1db\v\xbf\xa3\x8e\xf3cA\x7f\x97jA\n&\xec?T\xe4.\x14\x15>\x9e5\xfe\x9d\x94\x0fw\x11#\xb67\xf8\x9f\xeb\x86M\x90\x80\t7l<\x8e\xb8\x96\x95\x8f#\xd7\x06m< \x81u\xd7ϼQC\x98#\xfa\xa07\x9dA_\xe8\xcf\x1dH\x93\xaa\xc0\xf5<\x00\xeb.\\T\xc5\xf9aq\f\xf9\xe8R\xbc\x06v\xab.\xbd7\x03\x9a\xd3\xee\x03\x1d\x85XN\x14H]V\xa1-\xd0O\xd9/z4\x0f\x19\x93=\x1c\xffܴ\x1e£\x1bf\xcb\xdc\x1b\x98`\xc7\b<\xefV\x17/!\x98`\xfe[ۦ>\x19\xdfڸ\x85|\xa7A\xffV\xfcd\xf5\x92|\x82\xbe\xa3\xdf\x1d\x96\x86\x1cs\fpUE\x9a\xacĭ\x92[\x05\xba\xcftK\xf2w\xca\f\x13ۏR\xdd\xf2j\xcb\xc4\xe7\xe1\x83!c\x8do\xa92\xcc2\xad\x1bOl\xa0LP\xce\xfe\x19\x93O\xed\x97Ӏn\x067JK\x920\x8c\xa1\x17\xef\xc1ڪ\x83\xfb\xfb\xa8(,=^O\xb1;\x02M\xa6dcm\x1346E\xe8\xf6\x92|\x92\xd1\x05\xee\x13tX\x17\xa65\xad@\x9b%l6R\x19\x17\xaf].\t\xdb\x04'\x82\x95\x1d\xe89rW\n\x12\x16\v\xb4֩\x0f\x8d\x1aB\xb7\xafBm\x8a\x05\xc7\vzp\xb1\x19\x9ae\x95\xb5\x94\xae\xb4\xa1\xc5[\x0e\xd6\xf4\xd2\x00\xdd\xedӬm\xf2\xfe\x8c~\xa3s:\x8d\xc2]\xd5\xe7\xf1\x9a\xec\xcf\xe8.z1_\xd1y\xa7\xfcH\xf1\xa6ۓV\xed\xdf\xfd\xb7\x11g\x91\a{nwQ\xcb[\x14\x06\xfe\xaa\xfe\xa2\xa8V\xea\xfd\x88r:oI\vߓ\xff\xe5\x7f\x03\x00\x00\xff\xff\xe1\xa0\x1ak\x81\x7f\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xccYI\x93b\xb9\x11\xbe\xf3+2b\x0es\xe9\aݶ\x0f\x0e.\x0e\x9a\xb2#:\\\xed\xaah\xca\xe5\xeb\b)\x01\rzҳ\x16h\xbc\xfcwGj\x81\xc7[\x1a\xaa\xed\x18\x8f.UOK*\xd7/3EUU\x13\xd6\xc8W\xb4N\x1a=\a\xd6H\xfc\xeaQӗ\x9b\xee\x7f\xef\xa6\xd2\xcc\x0e\x1f&{\xa9\xc5\x1c\x96\xc1yS\x7fAg\x82\xe5\xf8\x80\x1b\xa9\xa5\x97FOj\xf4L0\xcf\xe6\x13\x00\xa6\xb5\xf1\x8c\xa6\x1d}\x02p\xa3\xbd5J\xa1\xad\xb6\xa8\xa7\xfb\xb0\xc6u\x90J\xa0\x8d\xc4\xcbՇ\xf7\xd3\x0f\xbf\x9b\xbe\x9f\x00hV\xe3\x1c\u058c\xefC㼱l\x8b\xca\xf0Drz@\x85\xd6L\xa5\x99\xb8\x069ݰ\xb5&4s\xb8,$\n\xf9\xf6\xc4\xf9\xc7Hl\x95\x88=fbq]I\xe7\xff<\xbe\xe7Q:\x1f\xf75*X\xa6\xc6؊[\xdc\xceX\xff\x97\xcb\xd5\x15\xac\x9dJ+Ro\x83bv\xe4\xf8\x04\xc0q\xd3\xe0\x1c\xe2\xe9\x86q\x14\x13\x80\xac\x9aH\xad\x02&DT6S\xcfVj\x8fviT\xa8\xf5\xf9.\x81\x8e[\xd9\xf8\xa8\xcc$\vda\xa0H\x03\xce3\x1f\x1c\xb8\xc0w\xc0\x1c,\x0eL*\xb6V8\xfb\xabf\xe5\xffH\x0f\xe0gg\xf43\xf3\xbb9Lөi\xb3c\xae\xac&\x1b=\xb7f\xfc\x89\x04p\xdeJ\xbd\x1db\xe9\x919\xffʔ\x14\x91\x93\x17Y#H\a~\x87\xa0\x98\xf3\xe0i\x82\xbe\x92\x86\x80T\x84P4\x04G\xe6\xf2=\x00\x87D%\xeah\x98Sջ\xeb\x8amb\x05^;T\x12\xff4\x93\xb9o\x91-\xfe=\xe5\x16\xcf$\x9dgusEw\xb1\xc51bW\xaax\xc0\r\vʷE%+\xa9\xb6_^\x8b\xd5 \x9f\x8at\xea\xeaƇ\xab\xb9t\xeb\xda\x18\x85,QI\xbb\x0e\x1f\x92\x17\xf2\x1d\xd6l\x9e7\x9b\x06\xf5\xe2\xf9\xd3\xeboWW\xd30\xe4H\x9d\xa0 ñ\x96mvh\x11^c\xfc%\xbb\xb9,ڙ&\x80Y\xff\x8c\xdc_\x8c\xd8XӠ\xf5\xb2\x04K\x1a-,j\xcdvx\xfaWu\xb5\x06@b\xa4S \b\x940\xf9U\x8e\x1f\x14Yr0\x1b\xf0;\xe9\xc0bcѡN0E\xd3Lg\x06\xa7\x1d\xd2+\xb4D\x86b;(AXv@\xeb\xc1\"7[-\xffq\xa6\xed\xc0\x9b\xec\xcc\x1e\x9d\x87\x18\xa1\x9a)rր\xef\x80iѡ\\\xb3\x13X\xa4;!\xe8\x16\xbdx\xc0u\xf9\xf8L\xd1 \xf5\xc6\xcca\xe7}\xe3\xe6\xb3\xd9V\xfa\x82\xd0\xdc\xd4u\xd0ҟf\x11l\xe5:xc\xddL\xe0\x01\xd5\xcc\xc9m\xc5,\xdfI\x8f\xdc\a\x8b3\xd6\xc8*\n\xa2\x13\xa4\xd6\xe2\a\x9b1\xdd]]\xdb\v\xe94\"\xa4\xbe\xc1<\x04\xaf\xc9e\x12\xa9$\xe2\xc5\n4E\xaa\xfb\xf2\xc7\xd5\v\x14N\x92\xa5\x92Q.[{z)\xf6!mJ\xbdA\x9b\xcem\xac\xa9#MԢ1R\xfb\xf8\xc1\x95D\xed\xc1\x85u-=\xb9\xc1\xdf\x03:O\xa6\xeb\x92]\xc6,\x06k\x84\xd0D\x90\xe8n\xf8\xa4a\xc9jTK\xe6\xf0\x17\xb6\x15Y\xc5Ud\x84\xbb\xac\xd5\xce\xcd\xdd\xcdI\xbd\xad\x85\x92SGL;\x88\x06\xab\x06\xf9U\xdc\tt\xd2Rdx\xe61FWGA\x19*Ɠr\x19\xc3 A\x83q\x8e\xce}6\x02\xbb+\x1d\x96\x17\xe7\x8dW<6hk\xe9bz\x85\x8d\xb1\xdd\xcc\xc3\xceH\xde\x1e\x05\xf1\xba\x06\a@\x1d\xea>#\x15|A&\x9e\xb4:\x8d,\xfd\xcdJ߿hĐ4\x12\x8b\xab\x93\xe6\xcfh\xa5\x117\x84\xff\xd8\xd9~V\xc1\xce\x1ca\x13\xfd_{u\"\xecr'\xcd\xfb\xa8]\xc6\xe2\xf9SA\xf0\x14[90\xb3\xae\xa6\xb0\xc8Am6\xf0\x1e\x84tTH\xb8H\xb4\xaf,\x1dT,4\xe6\xe0mx\x93\xf8\xdc\xe8\x8d\xdc\xf6\x85n\xd7Fc\x1es\x83tGs\xcbx\x13\xa1\x16yGc\xcdA\n\xb4\x15Ň\xdcH\x9e9\t6e\x90\x8dD%z\xd84\x1aeQ\x14\x8b\x82\x82\x9a\xa9\x1b6\\\x9e7\xc6J\x9aI\x9d<\xf8B b\x8d\xadsj\xd6\x1e\xb5\xc0n\xb6\x89ܘ\bh\x0e\x05\x1c\xa5\xdf%\xa4TCq\aߌ=\x1a{<\rMwx\x7f\xd9!\xedL\x89\x17\xc1!\xb7裷\xa1\"\xf7!W\x9a\x02|\x0e.bm\x17'ʈ\x05_9\xbd\xc7S_\xd1p˸\xb9\x14\xba\xcdr/{\x95A\xa5y\x11\xc4\xe2\x06-\xea^\xb5P\xc6@\x06\xa0\xb6\xc7j\xf4\x18\x93\x800\xdc\x11\xfesl\xbc\x9b\x99\x03ڃ\xc4\xe3\xech\xec^\xeamE\xe6\xa9r\xbc\xcdb33\xfb!\xfe\x19\xb9\xef\xe5\xe9\xe1i\x0e\v!\xc0\xf8\x1dZ\xb2\xf1&\xa8▭\xaa\xea]L\xde\xef H\xf1\x87\xefQ\xa2iR\x98ݡ\xc8U\f\x95\x13U\x87\x91'\xd2\xdb*\x99\xd0X\xa0\xfcK\x9eQg\xd3'`\x1a\xf2ڡ\xb2\xb6=\b\xc5(\xdd\f\xc1\xef\x1e\xfb\xc8\xfb\x8d\x98\x04\xf8Z]\xecTլ\xa9\xd2n\xe6M-\xf9\xa4+m\xac\xbdo\x84o\xa9\xf5\xa5\x16\x92Smx\x1dv\xa5\a\x12W-\xc1\x80\x1a\xbaM\xc2\x18\xd8\f\xab)\x89\x9bS\xed\r\x8e\x9f\xda{/\x9dcB\xbe\x9c>\x1dz*\xdb\x1ch\xa4\xf4\xcal_\xcf\x11o\xb8њ\x02\xdd\x1b`g\x14\xfd\xd1u\xd3\xc7\x1b\xc1g\x1d\xf8\x1e\a\x14\xdf\x13\xe5c\xdcXt\x9c\x8e\x11/\xc1a\xc4\xf5[l\xc0\xed\x88\xe0l\x89\xf6\x1e^\x96\v\xdax\xce\xc0\f\x96\vX\a-\x14\x16\x8e\x8e;\xd4Դ\xc8\xcdi\xf8.\x1a/\x8f\xab\xa2\xd5X\xbc䶣\xe8vX\x86\x94\x1e\xe6\xb0>\r\x94\x1bw\b\xd9X\xdcȯw\b\xf9\x1c7\x16\x857\xcc\xef@j'\x05\x02\x1bP\x7f\xaa\x03G\x04=\x97\x16O\x19s\xbe\xc3<\xdf\u0086\xc4\xce[\xe0\xa1\xe8\xf8F\xfc<\xe7mg-\x94\xef\x9c<\xae\xcḇ8\x1e\x94\xe8p~\xd3\xf8S*\xde\xf8@\x16\xbeb\xe6\xb5\x7f\xe2\x1bE`yY\x19\nf*9\x8c\xb5\xe8\x1a\xa3\x05\xb5l\xf7\x95\x80\x17\x96\xffw\x85\xe0\xb0Y\xabk\x94\xeb\xac\x15+\xdc\xd5\x05\xc5W\xa47\xf7A\xe9m\xad\xdde\x98\xb5\xa3\xfe\xf4\xd2\nud\xfcE:\xa0\xc1\x8a\xa6\xd5\x16Qg\xae!\xe8X\x18ƒa:\x99\f\x1cy\xa0&\x9cR\x98\x98\x93p6\x9e\xd4\xe6H\xa7[\xe4\"\x050:%|\xea\r\x99\x16\xb9+\xa7\xa5\x01\xcaG\xa9\x14\x15\x01\x16kCڢ\xb2֢:\x01s\xe4M\x87\xdfL\xdf\xff\xffZ.Ŝ\xa7\x0e\n\xc5\x17<\xc8\xfe\xd3\xd4}\xfa~\xecQ)\xf0p\x0e\x1a\xfa\xf8\xa9t\xeb3\x9b\xb7\xfd\x04\x1b\xa9\xa8\x98la\xc7\x1d\xe5\xc1\xc0\xc3\xea\xc7\xd5\xe3\x8f.\xf6\x10\xa8\xbd\x83#Y\xd0E\x96\xa8i0\xf9\x85$8OY\xe4\xb6\x03\x14{&/\x00e\xf4\x96*\xcf\xf4\\B%^\xf2'cA\xa0\xa7l\xa5\xb7\xc0wLo)6\x86@?r\x9c\xd9o3J\xee3\xea!R\x8f\xb8\xc7]\x16}\x91C=\xc1[\xac9\xfe\x8e}\xe6?\x9b\xf6\xf2\\\xdaQ\xfc\x18\xd8\x16St\x17K2'EW\xfe\xf2\xb6}\x19\xdf\xdf`\xf7\x1fοW=\xff\xd5S\x7f\xef\x89\xffW\xa1\x9c\x9a*ݛ\xe5\xf3\xe7\xb4+=x\xe6#\xc0\xd6&\xf8\x81\xec\xdfr\xf8\xc1\xa0\x8e\xbff\xbc\x85\xc7\xf8\x1bͭ\x02\x85\xf6\x14\x8b\xf0`m|\x14-\x8fu\x11*\x86\xf2\xd2\xfd\x10\xbc\xe8\xfc\x94\xd4^\xeb\xff\xd0t\x87\\\x83y\xba7\x99rmˮY\xc9홰>?u\xcf\xe1\x9f\xff\x9e\xfc'\x00\x00\xff\xff\xf3/:\xb2\x01\x1d\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcVMs\xdb6\x10\xbd\xebW\xecL\xaf%\x15O{\xe8\xf0\xd689x\xdaf4v&w\bX\x89\x88A\x00\xdd]\xc8u?\xfe{\a\x00)K\x14\xe5$\x97\xf0&`\xb1\xfb\xf0\xde\ue0da\xa6Y\xa9h?!\xb1\r\xbe\x03\x15-\xfe%\xe8\xf3/n\x1f\x7f\xe1ֆ\xf5\xe1f\xf5h\xbd\xe9\xe06\xb1\x84\xe1\x1e9$\xd2\xf8\x0ew\xd6[\xb1\xc1\xaf\x06\x14e\x94\xa8n\x05\xa0\xbc\x0f\xa2\xf22\xe7\x9f\x00:x\xa1\xe0\x1cR\xb3G\xdf>\xa6-n\x93u\x06\xa9$\x9fJ\x1f\u07b47?\xb7oV\x00^\r\u0601A\x87\x82[\xa5\x1fS$\xfc3!\v\xb7\atH\xa1\xb5a\xc5\x11uο\xa7\x90b\a/\x1b\xf5\xfcX\xbb\xe2~WR\xbd-\xa9\xeek\xaa\xb2\xeb,\xcbo\xd7\"~\xb7cTt\x89\x94[\x06T\x02\xd8\xfa}r\x8a\x16CV\x00\xacC\xc4\x0e>dXQi4+\x80\xf1\xda\x05f\x03ʘB\xa4r\x1b\xb2^\x90n\x83K\xc3D`\x03\x06Y\x93\x8dR\x88\xfa\xd8c\xb9\"\x84\x1dH\x8fPˁ\x04\xd8\xe2\x88\xc0\x94s\x00\x9f9\xf8\x8d\x92\xbe\x836\xf3\xd5\xd6\xd0\fd\f\xa8T\xbf\x9d/\xcbs\x06\xccB\xd6\xef\xafA`Q\x92x\x02Q\xea\xda\xe0\x81N\xf8=\aP\xe2\xdb\xd8+>\xaf\xfeP6\xaeU\xae1\x87\x9bʴ\xeeqP\xdd\x18\x1b\"\xfa_7w\x9f~z8[\x86s\xac\v҂eP\x13\xd2L\\e\r\x82G\b\x04C\xa0\x89Un\x8fI#\x85\x88$vj\xad\xfa\x9d\f\xcf\xc9\xea\f¿\xcd\xd9\x1e@F]O\x81\xc9S\x84\\H\x1c\x9b\x02\xcdx\xd1J\xaee \x8c\x84\x8c\xbe\xceU^V\x1e\xc2\xf63jig\xa9\x1f\x90r\x1a\xe0>$g\xf2\xf0\x1d\x90\x04\bu\xd8{\xfb\xf717\xe7{\xe7\xa2NI\xa1$\xb7\x9dW\x0e\x0e\xca%\xfc\x11\x947\xb3̃z\x06\xc2\\\x13\x92?\xc9W\x0e\xf0\x1c\xc7\x1f\x99D\xebw\xa1\x83^$r\xb7^\xef\xadL\x96\xa2\xc30$o\xe5y]\xdc\xc1n\x93\x04\xe2\xb5\xc1\x03\xba5\xdb}\xa3H\xf7VPK\"\\\xabh\x9br\x11_l\xa5\x1d\xcc\x0f4\x9a\x10\x9f\x95\xbd\xe8\x9e\xfa\x15\x17\xf8\x06y\xb2'\xd4\x1e\xa9\xa9\xea\x15_T\xc8K\x99\xba\xfb\xf7\x0f\x1faBR\x95\xaa\xa2\xbc\x84^\xf02\xe9\x93ٴ~\x87T\xcf\xed(\f%'z\x13\x83\xf5R~hg\xd1\vp\xda\x0eVx\xea\xd8,\xdd<\xedm\xb1\xdd\xec\x00)\x1a%h\xe6\x01w\x1enՀ\xeeV1~g\xad\xb2*\xdcd\x11\xbeJ\xad\xd3\xc7d\x1e\\\xe9=٘\x9e\x81+\xd2.\f\xffCD\x9d\xc5\xcd\xfc\xe6\xd3vgu\x1d\xab] x\xea\xad\xee\xa7\xe1\x9f\xd1t4\x8as\xfe\x96\x8d!\x7f/v;߹zy(\"[\xc2Y\xc36p\xe1ݯ\xf3RL\xf5\x1b\x99\xa9\x8e>r\xa3\x13Qi\xbe\xa3ϫ\xa5C_\xcb\x05\x12\x05\xbaX\x9d\x81z_\x82\xca?\x06e=\x83\xf2\xcf\xe3A\x90^\t\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;\xefwf\xbc\xc7/\xbd\r\xde\xeeU~]\x8c\xbd\xca[\xf2\x9d\x88\xf09V\xe8\r\x12\x86\xbd\x02\xbf(\xeaf#\x02\xbctJvicjt\x16\xf7\x10\xacTsRy\x05|\xd6\a\xe5qf؊4\x843f\x06\x7fb>\xa3j\xe7\x0e(\x06\xa5\xb9J\x19IP\f\xef\xd0\xc6\xe4?R-\xa3\xf7\xe9\xea\xc9V~qL7\\+\x8e\xa3\xa2\xfc\xf5x\xff\x86B\xde\xee=\xd3KZ(\x93\xd18\x8fEP-\xbf\x8cx\x8d52i\xd7)\x19\xf9;~\xb9\x1d\x135[Q\xfc\xe6T\x1e\xac7 ~\xda9f!G\x93\xef\xef\xe9\xdb4\x05\xc4\xc0\xcf(\x90\xc2\xcc`\xac\x10j\xd4HXC\xf5\x9ao\xa4\xd7@؟\xe2n\xac\xef\x05\xad\x80\xef\xf5\x82\xd4L\x1b\x99\xa8\xb5\xa84\xae\x80|<\xd7e\xb3\x89\xbbN\x84\x991<\xca\xf9\x81}\xe6\x1ac7\x8c\x17;\x03\xce\xde\x1b\x05|\xc1\x97\x19냷\x12C\xc0\xd31:\x9b\xc9\xec\x10\x9c\x18\x03?\xbe\xea\x03\x96\x86\xbf\x02\x83\xe5\xff\x00\x00\x00\xff\xff\xafA\x18\x17\"\x0e\x00\x00"), + []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=]\x93\x1c)r\xef\xfa\x15\x19\xf2\xc3\xda\x11ӣS\xf8\x1e\x1c\xf3&\xcfJ\xd6\xf8\ue909\x19Y\xfbLWewqCA-P\xd3\xea\xb3\xfd\xdf\x1d$P\x1f\xddT\x15\xdd\xf3\xb1\xbb\xe6E1Ր@~g\x92\xa0\xd5j\xf5\x865\xfc;jÕ\xbc\x02\xd6p\xfcaQ\xba\xbf\xcc\xe5ÿ\x99K\xae\xde=\xbe\x7f\xf3\xc0ey\x05\u05ed\xb1\xaa\xbeC\xa3Z]\xe0ϸ\xe1\x92[\xae\xe4\x9b\x1a-+\x99eWo\x00\x98\x94\xca2\xf7ٸ?\x01\n%\xadVB\xa0^mQ^>\xb4k\\\xb7\\\x94\xa8\tx\x9c\xfa\xf1O\x97\xef\xff|\xf9\xa77\x00\x92\xd5x\x05\x1a\x8dU\x1a\xcd\xe5#\n\xd4꒫7\xa6\xc1\xc2\xc1\xdcj\xd56W\xd0\xff\xe0DŽ\xf9\xfcZ\xef\xfcp\xfa\"\xb8\xb1\x7f\x19~\xfd+7\x96~iD\xab\x99\xe8'\xa3\x8f\x86\xcbm+\x98\xee>\xbf\x010\x85j\xf0\n\xbe\xb8i\x1aV`\xf9\x06 ,\x9d\xa6]\x85U?\xbe\xf7 \x8a\nk\xe6\xd7\x03\xa0\x1a\x94\x1fno\xbe\xff\xeb\xfd\xe83@\x89\xa6м\xb1\x84\x80\xffYu\xdf!.\x14\xb8\x01\x06\xdfi\xa3n5\x84x\xb0\x15\xb3\xa0\xb1\xd1hPZ\x03\xb6B`M#xAx\a\xb5\x19@\x8a\xa3\fl\xb4\xaa{hkV<\xb4\rX\x05\f,\xd3[\xb4\xf0\x97v\x8dZ\xa2E\x03\x85h\x8dE}\xd9\x01j\xb4jP[\x1e\xb1\xecۀw\x06_\xe76\xe6\x9aÅ\x1f\x05\xa5c\"\xf4[\b\xf8\xc42\xa0\x0f\xd4\x06l\xc5M\xbfո=`\x12\xd4\xfa\xefX\xd8\xcb\x03\xd0\xf7\xa8\x1d\x180\x95jE\xe9x\xef\x11\xb5CV\xa1\xb6\x92\xff\xa3\x83m\xdc\xc6ݤ\x82Y4\x16\xb8\xb4\xa8%\x13\xf0\xc8D\x8b\x17\xc0dy\x00\xb9f{\xd0\xe8\xe6\x84V\x0e\xe0\xd1\x00s\xb8\x8e\xbf\x11\xf1\xe4F]Aemc\xae\u07bd\xdbr\x1b%\xaaPu\xddJn\xf7\xefH8\xf8\xba\xb5J\x9bw%>\xa2xg\xf8v\xc5tQq\x8b\x85m5\xbec\r_\xd1F$I\xd5e]\xfeSG\xd4Ѵv\xefx\xd4X\xcd\xe5v\xf0\x03\t\xc4\t\xe4q\xa2\xe2\x19σ\xf2[\xec\xa9\xe0>9\xd4\xdd}\xbc\xff6dJn\x02Q\x06\xbc9E\x1f\x87M.7\xa8\xfd8bM\a\x13e\xd9(.-\xfdQ\b\x8e҂i\xd75\xb7\x8e\r~m\xd18~W\x87`\xafI\xeb\xc0\x1a\xa1mJf\xb1<\xecp#\xe1\x9a\xd5(\xae\x99\xc1W\xa6\x95\xa3\x8aY9\"dQk\xa8K\x0f;{\xf4\x0e~\x88\x1aq\x82\xb4A\x8b\xdc7X\x8c$\xcd\r㛨.6J\x8f\x94\x8c\x1b2\xc6QZ\xf8]\xf3Zĩ\xc5\xc3_\x96\xb8̵\x7f\xefF;~s+k%\xff\xb5ER\xa6^\xfc\xf1X_\xe9\x81j\x1f7\xc7F\x87ԝD\xb4k\xf8\xa3\x10m\x89e\xa7\u05cf6\x98\xb3\x8d\x8fGP\xc8\xe81.\x9d\x109\xeb\xe3\xf6\"\xfb_I\x813\x8d \x95M\xc0\xe3\xd2\xc3\x03.\t\x03I\x9aPG\x8bubų[\x06\x90\xad\x10l-\xf0\n\xacn\x8f\xd1\xe8\xc72\xad\xd9~\x02[\xd1\x03x\x12\xb2: A\xd5\b^\x10\xc9;\x85B\xf8\xfa㢊\x1b\xa7(\xe3.o\x95\xe0\xc5~\x01_\x1f\x93\x83\xa2\xb4\x06\xd9\r;\x845V\xec\x91+\x9d\x12\x03\xa5\xa9\xeb\xc0\x9e\xf7jZ9-\x19\x80\x1cڸ\xcc\r'\x91U)\xf5\xb0\xc4\x10\x9f]\x9f\xde:@A\x0ee\xb7\x95@\xed`\xbb\xd7\b\xf8\x03\x8b\xd6&\x96\tP\xb6d\x9a\x94\x86F\x19;M\xf7i\xd5\x05C\xe7(\xf5\xe3\f\xd3\x1c\xed,\xc9\xea\xbe\x05%\x1c\x89\xeap0R\xc8J\xa2\xdbF\xed\x88\xda\xf7ժ\xf5}'\x91\x02kf\xb0\x04%'g&vi\x05\x9a0WI\x9c\xd1롋~\xff\xe4\xf1\x80`k\x14`P`a\x95>Ff\x0eJ}\xcbQ\xac\x13\xa8Lhӱ\x04\xf4\x1b\x98\x01\t\x8e\xd3w\x15/*\xefa8\xf6$8P*4N\x9b\x90˼\x9f\xda$,\x91?L2\xa7=\xfa\xb6 V\x87\xf0R\x1a\xa5o\x19j\xb8oI\xd4\xf6\xba\xf7H\xb7\x84\xefV\xcdn\xfb\xff'b\xa319\x83ig\xe4\x1f\xc8\xfd\xcc\xe6\xe9I\xbe\xa5\b\x0f\xcd%\xdcl\x00\xeb\xc6\xee/\x80\xdb\xf8uI\x12\x98\x10\x839\xfe\xc0\xb49\x9d\xe93I\x93#\x13/D\x98n\x8a? ]\xc8d\xdc\a\x8b\x91M\x93\xbf\x0eG]\x00\xdftH//`ÅE}\x80\xfd\xb3T}\xa4\xccs #\xc7\xea\x01\xe5\tlQ}\xfc\xe1\\\x1c\xd3'\xc12\xf1r8\xd8\xfb\xc61\x82\x18\x9b\xe7\x05\xb8@\xf12\xd7XS\x1c\x0e\xdf\b\x9b\xfd\x17r\xaa?|\xf9\xf98V>l\x19\x9cw\xb4\x91\x05\xa1\xf3\xed\xc3\xc1\x8e\x86\xeb\vQA\xfc\x85|\xa0.\xa8\xf29\x97\v`\xf0\x80{\xef\xba0\t\x8e>,vΘ^#%\x7f\x88\xcf\x1epO`\xd2ٜ\xe3\x96\xcb\r\xbe=`\xc2\xf5O\xb5\x11\x0eݚBX\xec\xf1\xe4>\x10\"(\x86\xcfe\x03߂($r'閩Kb\x8b\xb8?c\x9bY\xac2\x9cc\x98\xfa$\x0e\xf8\xc9xZ:\x89\xa9x\xc8i\x1a$\x99\xc9%\xa8oߙ\xe0e7\x91\x97\x91\x1by\x01_\x94u\xffP\x80f\x88Q~Vh\xbe(K_^\x04\xa3~\xe1/\x89O?\x03\t\x9a\xf4Z\xde!l\x98\xf3\xf36\xcdq[\x87{n\xe0F\xbaxţ$s*J\xef\xfa\xe9\xfcDuk(]'\x95\\\x91\xcdL\xce\x14\xf0\xad\xf4\b\xddO\x9e4L\xf8\xcd\x19\v\xff\x8bO2\vV`\x19#K\xca~2\x8b[^d\xceW\xa3\xde\"4N\x85\xe7qD\xa6b\r\xbb9\x8d}\xf2\xacwlA\xf1\x96ˋY9\x81\xcb\xe8\x15ɸ\xd8u\"\xb39\xdduyGdE\xc9\xc5X\xc4.+K:\xc2b\xe2\xf6\x04\x8d~\x02-N\x15\xcd\xc1ڽ\t\xacY\xe3\xc4\U000bf765#n\xfe_h\x18\xd7\xe6\x12>\xd0I\x95\xc0\xd1o!\x0f6\x00\x931e\xe3\xa6r,\xf0Ȅ\xb3\xbdN\x81J@\xe1-\xb1\xda\x1c\xf9%\x17\xb0\xab\x94\xf1fs\xc3Q\xd0y\xc1\xdb\aܿ\xbdp\xd3/N9\x14\xf2\xb77\xf2\xad\xb7\xe1G\x02\xdb\x19|%\xc5\x1e\xde\xd2oo\x9f\xe2\xcad2[f\xb7\x1f\xab\x87.ö\xaaY\xb3\n\fjU=\xa34d2Y\u07b7\x11\xc7\fs\xe3}R<8\xb9s\xbb\xcdb\xd1F\x19\xfb9\x9d\xb7\x9bX\xcfm\x1c1\xf6L\x139\xaeE\x8f=\xe4\xb1:}뜸\x8dE\x1dry^\aG\xff\xff\x89\x91Q\xeaTd\xb8\xd8.\x19Ǻ\xfc\xaaC\xf0\x027\xf9\x83\x93\x9c%\x9e\xe20:\xbc\x9c\xe8m\x7f\xfc1\xc8':\xc9u\x7f\x0f7\xf2\xdc\x0em\xa1\xea\x9a\x1d\x9e*f-\xf5ڏ\x8c<\x1d\x00y\xea\xebmK\xf2\x9ck\x11{\x1e\xa2\xf3\xc3\x1d\xb7\x15\x97\xc0\xa2\xda@\x1d\x18\x8aA\xa3R9\xe4T\xab\x98\x815\xa2\xecR\xe4\xbf\aS^syC\x13\xc0\xfbg7\xfdУ\xeb%\x9d\xcd\xeb\x8e&\x1d\xe5\xbb\x0f\xded5\xaa\x84]\x85\x1aG\x8cq\x9c\xf7&OQ*;H\x19\x9c\xe0\x106\xaa\xfc\xc9\xc0\x86kc\x87K0К\\Z\x9fH>\xb7\xeeo\xbcF\xd5ڗD\xf0\xc7~\x9a\xd1Yo\xcd~\U0003ab41ժ\xf5\xc6\xdc\xf2\xba;U\r\xe8\xdd1n\xbbc#ʟX\xe5H\xd0\b\xb4\bkܤ\xcf[S\xadP\xd2\xf0\x12u\xac\x12\xf0d\xe3\xca\t\xe6\x86qѦNiR\xed\xd4\bT~\xd4\xfa\xac\x00\xf4\xab\x1f9\xc8\xfbUj7FP\xe6\xde\xe9 \v\x81o\x80[@Y8\x8c\xa3\xf6*\x99\xa6\b\xc8 \xd4\xf0\\=\x97\xa7\xc0]C\xd9\xd6y\bX\x91@r9\x9b\xf2\x1av\xffĸx\t\xb29\xce\xfb\xa4\xf4\x1d\xb2\xf2\x9c\x1c\xc9/\x83\xe1\x80Ҵ\x9a\x0e߽\xee\xd8q\x91\xb7fG9\x10\xac\x95E\x85\xa4\x84\xe4X7x\xf0\\\x1a\x8b,\x97\x17\x9cW\xd4J\xc9\xe56\x8fvىȾyT\xaf\x95\x12ȦO\x01\xfb\xe6p\xfd\n\x9a\xe8\x97~\x9a'j\xa2\x9e\b\xfeؚ\xe8\x90MQ\xa7\xb4\x80Y\xeb\xc2}\x129\x05\xba\x95C\xeb\xf2\x02\x8a\xe8\x94H:\xac\xe29Cd.y\x06mGt\xbd\x91\xdc\x0e\x9dG\a\xe2E\x9dG7A\xe7\x0e\x9c\x93\xe1\xba\x19\x01p\x02\x1a\xe3\x10Z{\xc75'8\x92k\x04V\x96X\xfaܡsEBX\xe2\v\xcf&\x8a\v\x92\xbb;\xdd\x13̢ll\xa3\xa0\x93\xf2\xa0\xfa\x11W\xad|\x90j'W\x14\x8c\x9b\x93uH\xae\xab\xf8\xcc\xd3۳\x95Ѳ~\xc9W\xd3KZh̯\xf9<\x15\xfd\xa7\x17\xd02\xd9|sR\xc2c\x8e\v\x96\xf4\x9a/\x80\x9e\xf8qq\x15s\xf3\xcf\f\x0e\x87\xc2\u05feX\xf9Iei7iP\x03\xa7pW\xa1\xadP\xc7\xd2\xe8\x15\x95\x84\x97\xb3'\x94}\xf0\xd2թ9\xa6\x8a.\xb2/\xbf<\xa8\\\xa3\xe8\xa6\x15\xe2\xc2\xf16kE2\x1c\xb6\x8aD옳\xb2\xea\xb7\xd2\x1eCN\xf5C6\x1e\x87\x95\x0e\xe3\xfa\xbe\xae\n!\x16\xf8\xa98s\xa0qj\xbfT\xd898_\x1f\x973P\xfe/.\xff7/\xfd˨T\xc8Gcn\x95d\x87\xc4\x04\xac\x04\x83\r\xd0\xd8\xd77\x84~\xa1\xd0\xf6\xf7\x85S\x8b\xf5\xd7&H̤\v\x9b\x81\xd6\x04\x9c\x83z\x0f\xb2\x06\xad\xf1\xae@g\aB\xceЍ\xffP\xf8[\b\x11L\x8a_\xbfU\x18\xc57T\xcfs\x03\x7f\x86J\xb5\x89\xaa\xba\x19\x94-TW,oxTh\x11\x0e\x14в\xc7\xf7\x97\xe3_\xac\ne\x17\x94EK\x00\xa2\xa0\xa8\xcf\xccrY\xf2G^\xb6LD\xa9\xedk\xf8=\x03\xf5|\x96\x80\xa64H.<\x03\xc6\xf1#\x86\x83\xaf\x8d?\x969Y\xc5\xcd\xfb\xa2y\xd5\x19g\xd7d\x8ck.&\xac\xe1\xa9\xc7\x17\xcfR\x85\xfa\x9b\xd4Z\x9c^a\x91\x13I,TS\x9cQC\x91Y\xac\xf5\xe4\xf3\x96\x9c*\x89Sb\xee\x17\xab\x88x\xfe:\x88,\xfc,\xd7<\x9c\x82\x9d\x17\xafoxŪ\x86שeȬ`x\xbeR\xc4\xe7\x88;\xa6\xeb\x11\x16\xab\x10\x9e\x14\x97d\xd4\x19\x9cR]\xb0\x88\xb1<\xd6\x7f\xb5\xfa\x81W\xab\x1ax\xddZ\x81Y\x96\x98\xfd\xf1\x94j\x80.v\xf9\x1bk\x1a.\xb7\xc7L\x91\xcb:\xb3l\xb3\xcc2_\x0e\x162\xe2\x99a\x88\xd1Gl\x13ᨿB\x9c\x88\xeeb*\x91K\xab.\xe1\x83\xdc\a\xb8\t8\x83\x90N*{t\xb9\xcb-kDž\x18\xde`\"\xb0\xf3\xa0\xc2=B\xc3j\xbf\xaa)\x0f\xa5\x88\xc7\xe1_T\x89\xb7Jۥ`\xe1\xf6\xb0\x7f\xe2\xb4q\x10@)Q\x82\x8c]\x13\xbb$\x97?\xb8\xfb\xe7m*}0\x18\xddۿ\xa9ҭm\xe9\x1c\xe2\xee\xa0\xfb\xd1}\xda\rj\x94\xfe)\x8a\xff\xbc\xff\xfa\xa5\x83\x9f\xf2A\x83\xa7z\xf0\x04\x82\xf7(ʀ\x9cp|\x15\n~<\xb6\xc8&?\xf3\xd9\x01k\xf8\x7f\xd0\xcbcOH\xcf|\xb8\xbd!\x18\xd1o\xa2\xa7̺J\x83\xeeTo\x8d\u0382t\xa8\x9a\x14\x8b\x9b\xcd\b\xe2\xb8*v\xf8\xd4\x0f\x96\xfeY\xa7h\xc1x\xac\x83r\x82w{\xe3\xd715\xcb'\xe7\xc4\xc9=(ϑ\x15\xd7\xe5\xaaa\xda\xee\x89m\xcc\xc5h\r\xd1b̥W&\x15\xeb\xf1SUI\xf4\xc6\x17\xaa\xe8\xbcnߌOD\x0fqw\xce:\xa6\xefh,\xde\xcex\xc6uL\x1b\xdf\x15a*\xf19Y\x84\xf1li\xab\xa0\x89n\xbf\x9f\x95\x06\xb9\xebF\xcf\xeb9\x17\xd5\xc6\xd4O\x02\x8c\x1bO\xaa\xceH֘*\xf1,\xd0\xd3t\x1d\xbd\x98e\x99m\x9f\xb2I\x0f`\xb4O^T\x03m\xb5è\xcf\xe2\xb6IZiXJ\xb7;\xdb\xeckC\xb8\xb8\x18D\xee\xafsl\x9a\xf9\xe4\xc8ُ\x8dx\xf4L\xa8\x1f\xcaF9\xd5v\x8c\xa93\x0eL\x17]\xbb\x8cB\xdcy\x7f4\xf3\xa9\x8a<\x83q\xc6\xf3\x14\x84\xaf\\\\A\xf2Պ̗)~SD\xcfh5STX\xb6\x02\xcf}\x97\xee~0~\xf9e\xba8[\xc6\xdbt\x0e\xd9\x03\x03\xed|\xe6\xf1\x1bx\x81\x12\x01\xf2\x90\x92S\x0e\x1f\x05\a\xfe\t\xac¿\x96X\x14h̦\x15\xb1\x92\xa7\xd0\xc8,\x96\xb1;7݊O\xaaEi\x1b\xa1X\x89\xfaZ\xc9\rO\x9cX\x8c\xd0\xfa_\xa3\xce\a<[\xd0\xc7V\xf7\xcf\x0f\xce>\xdd\xf6$\xcd\xd50̈́@\xf1\x89\v4?\xab\x9dt\xeb\xca\x10\xc8\xdbԸ\xc1ݥ\xa2\xd5ά\xefA\xb6\xf5\xda9\xb9h\xedt\xb0\xb8Qz\xbe\x8a\xd8\xe3\x9dK\x8b[L\x85\xca;\xcd-\xde7L\x1b\xa4\x15e\xec\xe0\x97\x83!>\xfa\xdc\b\xb6\xf5\xe5b%/\x98\xc5\xce\x00\xd3\fS˧\xf1\x86`\x89=U降$T\xb6PO][\x98\x14\xeb\xa9'0\x13\xa6:\xf9\b\xa6\xb7\xc8\x05k,]\x12!:\x12\x11m\x80A\x0f\xcb\x1e\xbc\x839\x02;\xcdi\xa1\xd47\x14\x95\x19\xcb\xeaD\x94\xb0\xacw\xae\x8f\xc1\xd0ӵ\xba\x1cԦ\r\x1f\x01\xec\x8a\xd0`\xc7LWp\x9c\xf4\xbd{\xd8\x1e\f\xb9\xea\x0e4\x96\x80\x8f(\xc1\x89\"\xe3\x02\xcb9N\xfdF\x89]\xfd\x88\xfa'\xd3\xc1\xa1j9\xc7\xe2\xf7\x96i\xdb-\xfd؏\xd9(]3{\x05%\xb3\xb8r\xa3\xcfs\xdd\xd2Oyj}\xe6\xf1\x1c\xdd\xfe\n\xe2Qī)\xce\xfa\xf9;[5\x1aö1\bݡFآtx\xefr}I\x8f)^{\vƢ+\xbft(d\x85mY\x98\xc0\xbbp\xddif|C\x97\xa2\xd8\xed\xa4\x8aN\xab\x8ap\xc1\xee\x0e\x999|\x92\xf9\b\x17\x9f\x86}C\xd2\xd6\xef؟U0_\x04I\x8f\xf2Z\xdeE\xd6)\x99\xb6\x8af>ɜTJ=d\xb9ٟ\xbb\x8e}:\x89K\xcfJt\xadp\xadZ;\xf0s\x02\xc2\x13ˤ'*\x9fپ\x10\xcc\x0f\xfe\x92\xd1T\x9a4\xcf\xd3\xfb<\x82ԅ\xb7\xca2\x11\x8d\x8c\xe3ˮC5s\xc9\xfe>>\xf0+\xc4\xfe\xe2\x10\xf2\xc1\xcb\xe1=\xec\xaa\x7fn2h\x82\xfe\x8a\xf5TZ5d\xfd\x92@\xba\x97*{\x9fd\xea]\xc0%\xfbGP?Ѣ2p\xfc\xb9\xef=\x85G\xbfL\xef0\xa3LG\x9a@\xc1\x87\xad:\xc98c\xe93^jS1\xb3\xe4\x9e\u07ba>\x9d\xdb10W\x9d\x13z7!\x95黠+\xf8\x82\xbb\xc4W\x8f,:\x8d\"\xa9Jt\xb9\x91\xb7Zm5\x9ac\xa6[ѝ?.\xb7\x9f\x94\xbe\x15\xed\x96˯\xd3\xd5\xd1s\x9do\x99\xb6\xdc1\xad_Ob\xecu\xb4q\x89ߖGO\xff\xc0%\x13\xfc\x1f)]>\xfcqi\x86\x19}\xd7\x04\xe4\x9dc\xa1\"\xe2\x97\x14`\xd0\xd0?\x99\x81\xf9\x89\xf3^\xc2\x17\x95\x14\xe3p`\xcb\xc7@\xb9\x815\x1a\xbb\xc2\xcdFi\xeb\xf3\xf7\xab\x15\xf0Mt\x90\x9c\x86\xa08ѿ\xb8\x0e<\x95x\xef\x8e¢ò\t\xa9DMV\x87BΚ\xed}F\x92\x15\x85\x8b\t\xf0\x9d\xb1,\x15\x9b\x9e\x1d\xbb~?\x80qpM\xd0E\xb1\xfd41\xde\xfcg\xbeIɋ\xff\x1f\x84\xd6\x02\xff\xe5\xe8\xd7W\xbe\xee\xb7cZr\xb9=\v#\xbf\x84\xb1\x89x>\x80}Ɉ>\xae\xfc\xd9b\xfa\xa4Y:\xfaH\f^\x0e\xf0\x1cf\n_\xfe/\x00\x00\xff\xff\xe5\x9d;'\xe7k\x00\x00"), diff --git a/pkg/apis/velero/v1/download_request_types.go b/pkg/apis/velero/v1/download_request_types.go index a2e0404025..f23118fe50 100644 --- a/pkg/apis/velero/v1/download_request_types.go +++ b/pkg/apis/velero/v1/download_request_types.go @@ -25,7 +25,7 @@ type DownloadRequestSpec struct { } // DownloadTargetKind represents what type of file to download. -// +kubebuilder:validation:Enum=BackupLog;BackupContents;BackupVolumeSnapshots;BackupItemOperations;BackupResourceList;BackupResults;RestoreLog;RestoreResults;RestoreResourceList;RestoreItemOperations;CSIBackupVolumeSnapshots;CSIBackupVolumeSnapshotContents;BackupVolumeInfos +// +kubebuilder:validation:Enum=BackupLog;BackupContents;BackupVolumeSnapshots;BackupItemOperations;BackupResourceList;BackupResults;RestoreLog;RestoreResults;RestoreResourceList;RestoreItemOperations;CSIBackupVolumeSnapshots;CSIBackupVolumeSnapshotContents;BackupVolumeInfos;RestoreVolumeInfo type DownloadTargetKind string const ( diff --git a/pkg/cmd/util/output/restore_describer.go b/pkg/cmd/util/output/restore_describer.go index 8b805c354f..103ad12d86 100644 --- a/pkg/cmd/util/output/restore_describer.go +++ b/pkg/cmd/util/output/restore_describer.go @@ -20,10 +20,13 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "sort" "strings" + "github.com/vmware-tanzu/velero/internal/volume" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kbclient "sigs.k8s.io/controller-runtime/pkg/client" @@ -167,6 +170,21 @@ func DescribeRestore(ctx context.Context, kbClient kbclient.Client, restore *vel describePodVolumeRestores(d, podVolumeRestores, details) } + buf := new(bytes.Buffer) + if err := downloadrequest.Stream(ctx, kbClient, restore.Namespace, restore.Name, velerov1api.DownloadTargetKindRestoreVolumeInfo, + buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertFile); err == nil { + var restoreVolInfo []volume.RestoreVolumeInfo + if err := json.NewDecoder(buf).Decode(&restoreVolInfo); err != nil { + d.Printf("\t\n", err) + } else { + describeCSISnapshotsRestores(d, restoreVolInfo, details) + } + } else if err != nil && !errors.Is(err, downloadrequest.ErrNotFound) { + // For the restores by older versions of velero, it will see NotFound Error when downloading the volume info. + // In that case, no errors will be printed. + d.Printf("\t\n", err) + } + d.Println() s = emptyDisplay if restore.Spec.ExistingResourcePolicy != "" { @@ -361,6 +379,50 @@ func describePodVolumeRestores(d *Describer, restores []velerov1api.PodVolumeRes } } +// describeCSISnapshotsRestores describes PVC restored via CSISnapshots, incl. data-movement, in human-readable format. +func describeCSISnapshotsRestores(d *Describer, restoreVolInfo []volume.RestoreVolumeInfo, details bool) { + d.Println() + var nonDMInfoList, dmInfoList []volume.RestoreVolumeInfo + for _, info := range restoreVolInfo { + if info.RestoreMethod != volume.CSISnapshot { + continue + } + if info.SnapshotDataMoved { + dmInfoList = append(dmInfoList, info) + } else { + nonDMInfoList = append(nonDMInfoList, info) + } + } + if len(nonDMInfoList) == 0 && len(dmInfoList) == 0 { + d.Printf("CSI Snapshot Restores: \n") + return + } + d.Printf("CSI Snapshot Restores:\n") + for _, info := range nonDMInfoList { + // All CSI snapshots are restored via PVC + d.Printf("\t%s/%s:\n", info.PVCNamespace, info.PVCName) + if details { + d.Printf("\t\tSnapshot:\n") + d.Printf("\t\t\tSnapshot Content Name: %s\n", info.CSISnapshotInfo.VSCName) + d.Printf("\t\t\tStorage Snapshot ID: %s\n", info.CSISnapshotInfo.SnapshotHandle) + d.Printf("\t\t\tCSI Driver: %s\n", info.CSISnapshotInfo.Driver) + } else { + d.Printf("\t\tSnapshot: specify --details for more information\n") + } + } + for _, info := range dmInfoList { + d.Printf("\t%s/%s:\n", info.PVCNamespace, info.PVCName) + if details { + d.Printf("\t\tData Movement:\n") + d.Printf("\t\t\tOperation ID: %s\n", info.SnapshotDataMovementInfo.OperationID) + d.Printf("\t\t\tData Mover: %s\n", info.SnapshotDataMovementInfo.DataMover) + d.Printf("\t\t\tUploader Type: %s\n", info.SnapshotDataMovementInfo.UploaderType) + } else { + d.Printf("\t\tData Movement: specify --details for more information\n") + } + } +} + func groupRestoresByPhase(restores []velerov1api.PodVolumeRestore) map[string][]velerov1api.PodVolumeRestore { restoresByPhase := make(map[string][]velerov1api.PodVolumeRestore) diff --git a/pkg/cmd/util/output/restore_describer_test.go b/pkg/cmd/util/output/restore_describer_test.go index 0c297204dc..f72ee802f8 100644 --- a/pkg/cmd/util/output/restore_describer_test.go +++ b/pkg/cmd/util/output/restore_describer_test.go @@ -6,6 +6,8 @@ import ( "text/tabwriter" "time" + "github.com/vmware-tanzu/velero/internal/volume" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -237,3 +239,153 @@ func TestDescribeUploaderConfigForRestore(t *testing.T) { }) } } + +func TestDescribeCSISnapshotsRestore(t *testing.T) { + cases := []struct { + name string + inputVolInfoList []volume.RestoreVolumeInfo + inputDetail bool + expect string + }{ + { + name: "empty list", + inputVolInfoList: []volume.RestoreVolumeInfo{}, + inputDetail: true, + expect: ` +CSI Snapshot Restores: +`, + }, + { + name: "list with non CSI snapshot", + inputVolInfoList: []volume.RestoreVolumeInfo{ + { + PVCName: "pvc-2", + PVCNamespace: "ns-2", + PVName: "pv-2", + RestoreMethod: volume.NativeSnapshot, + NativeSnapshotInfo: &volume.NativeSnapshotInfo{ + SnapshotHandle: "snap-1", + }, + }, + }, + inputDetail: true, + expect: ` +CSI Snapshot Restores: +`, + }, + { + name: "CSI restore without data movement, detailed", + inputVolInfoList: []volume.RestoreVolumeInfo{ + { + PVCName: "pvc-1", + PVCNamespace: "ns-1", + PVName: "pv-1", + RestoreMethod: volume.CSISnapshot, + CSISnapshotInfo: &volume.CSISnapshotInfo{ + SnapshotHandle: "snapshot-handle-1", + Size: 1234, + Driver: "csi.test.driver", + VSCName: "content-1", + }, + }, + }, + inputDetail: true, + expect: ` +CSI Snapshot Restores: + ns-1/pvc-1: + Snapshot: + Snapshot Content Name: content-1 + Storage Snapshot ID: snapshot-handle-1 + CSI Driver: csi.test.driver +`, + }, + { + name: "CSI restore with data movement, detailed", + inputVolInfoList: []volume.RestoreVolumeInfo{ + { + PVCName: "pvc-3", + PVCNamespace: "ns-3", + PVName: "pv-3", + RestoreMethod: volume.CSISnapshot, + SnapshotDataMoved: true, + SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{ + OperationID: "op-3", + DataMover: "velero", + UploaderType: "kopia", + Size: 1234, + }, + }, + }, + inputDetail: true, + expect: ` +CSI Snapshot Restores: + ns-3/pvc-3: + Data Movement: + Operation ID: op-3 + Data Mover: velero + Uploader Type: kopia +`, + }, + { + name: "vol info with different entries, without details", + inputVolInfoList: []volume.RestoreVolumeInfo{ + { + PVCName: "pvc-3", + PVCNamespace: "ns-3", + PVName: "pv-3", + RestoreMethod: volume.CSISnapshot, + SnapshotDataMoved: true, + SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{ + OperationID: "op-3", + DataMover: "velero", + UploaderType: "kopia", + Size: 1234, + }, + }, + { + PVCName: "pvc-2", + PVCNamespace: "ns-2", + PVName: "pv-2", + RestoreMethod: volume.NativeSnapshot, + NativeSnapshotInfo: &volume.NativeSnapshotInfo{ + SnapshotHandle: "snap-1", + }, + }, + { + PVCName: "pvc-1", + PVCNamespace: "ns-1", + PVName: "pv-1", + RestoreMethod: volume.CSISnapshot, + CSISnapshotInfo: &volume.CSISnapshotInfo{ + SnapshotHandle: "snapshot-handle-1", + Size: 1234, + Driver: "csi.test.driver", + VSCName: "content-1", + }, + }, + }, + inputDetail: false, + expect: ` +CSI Snapshot Restores: + ns-1/pvc-1: + Snapshot: specify --details for more information + ns-3/pvc-3: + Data Movement: specify --details for more information +`, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + d := &Describer{ + Prefix: "", + out: &tabwriter.Writer{}, + buf: &bytes.Buffer{}, + } + d.out.Init(d.buf, 0, 8, 2, ' ', 0) + describeCSISnapshotsRestores(d, tc.inputVolInfoList, tc.inputDetail) + d.out.Flush() + assert.Equal(t, tc.expect, d.buf.String()) + }) + } +} diff --git a/pkg/controller/download_request_controller.go b/pkg/controller/download_request_controller.go index 78e7ff3859..22e9d87075 100644 --- a/pkg/controller/download_request_controller.go +++ b/pkg/controller/download_request_controller.go @@ -134,7 +134,8 @@ func (r *downloadRequestReconciler) Reconcile(ctx context.Context, req ctrl.Requ if downloadRequest.Spec.Target.Kind == velerov1api.DownloadTargetKindRestoreLog || downloadRequest.Spec.Target.Kind == velerov1api.DownloadTargetKindRestoreResults || downloadRequest.Spec.Target.Kind == velerov1api.DownloadTargetKindRestoreResourceList || - downloadRequest.Spec.Target.Kind == velerov1api.DownloadTargetKindRestoreItemOperations { + downloadRequest.Spec.Target.Kind == velerov1api.DownloadTargetKindRestoreItemOperations || + downloadRequest.Spec.Target.Kind == velerov1api.DownloadTargetKindRestoreVolumeInfo { restore := &velerov1api.Restore{} if err := r.client.Get(ctx, kbclient.ObjectKey{ Namespace: downloadRequest.Namespace,