From 11340621a1eb695d6afc649e2d55d3e02fa2fe5e Mon Sep 17 00:00:00 2001 From: allenxu404 Date: Wed, 8 Mar 2023 15:46:55 +0800 Subject: [PATCH] Add warning/error result to cmd `velero backup describe` Signed-off-by: allenxu404 --- changelogs/unreleased/5916-allenxu404 | 1 + .../v1/bases/velero.io_downloadrequests.yaml | 1 + config/crd/v1/crds/crds.go | 2 +- pkg/apis/velero/v1/download_request_types.go | 3 +- pkg/cmd/util/output/backup_describer.go | 40 +++++++++- .../output/backup_structured_describer.go | 74 ++++++++++++++++--- pkg/cmd/util/output/restore_describer.go | 6 +- pkg/persistence/object_store.go | 2 + 8 files changed, 113 insertions(+), 16 deletions(-) create mode 100644 changelogs/unreleased/5916-allenxu404 diff --git a/changelogs/unreleased/5916-allenxu404 b/changelogs/unreleased/5916-allenxu404 new file mode 100644 index 0000000000..98ea1429c1 --- /dev/null +++ b/changelogs/unreleased/5916-allenxu404 @@ -0,0 +1 @@ +Add warning/error result to cmd `velero backup 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 4c58a9d68e..9602c927b7 100644 --- a/config/crd/v1/bases/velero.io_downloadrequests.yaml +++ b/config/crd/v1/bases/velero.io_downloadrequests.yaml @@ -48,6 +48,7 @@ spec: - BackupVolumeSnapshots - BackupItemOperations - BackupResourceList + - BackupResults - RestoreLog - RestoreResults - RestoreResourceList diff --git a/config/crd/v1/crds/crds.go b/config/crd/v1/crds/crds.go index e89df169e4..744cd69fb1 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\x1c9n\xef\xfa\x15(\xe5\xc1wU\x9aѺ\xf2\x90\x94\u07bc\xb2]Q\xed\xc6VY:\xdfC\x92\aN7f\x86+6\xd9G\xb2G\x9eK忧\b\xb2\xbf\xd9ݜ\xb1t\xb7we\xbe캇\x04A\x00\x04\x01\x10\x84.V\xab\xd5\x05+\xf9WԆ+y\x03\xac\xe4\xf8͢t\xff2\xeb\xa7\u007f7k\xae\xae\x0fo/\x9e\xb8\xcco\xe0\xb62V\x15_ШJg\xf8\x1e\xb7\\r˕\xbc(в\x9cYvs\x01\xc0\xa4T\x96\xb9\xcf\xc6\xfd\x13 S\xd2j%\x04\xea\xd5\x0e\xe5\xfa\xa9\xda\xe0\xa6\xe2\"GM\xc0\xeb\xa9\x0f?\xad\xffm\xfd\xd3\x05@\xa6\x91\x86?\xf2\x02\x8deEy\x03\xb2\x12\xe2\x02@\xb2\x02o`ò\xa7\xaa4\xeb\x03\n\xd4j\xcdՅ)1ss\xed\xb4\xaa\xca\x1bh\u007f\xf0C\x02\x1e~\r?\xd3h\xfa \xb8\xb1\xbft>\xfeʍ\xa5\x1fJQi&\x9a\x99\xe8\x9b\xe1rW\t\xa6\xeb\xaf\x17\x00&S%\xde\xc0'7E\xc92\xcc/\x00\xc2rh\xcaU@\xf8\xf0\xd6C\xc8\xf6X0\x8f\v\x80*Q\xbe\xbb\xbf\xfb\xfa\xaf\x0f\xbd\xcf\x009\x9aL\xf3\xd2\x12Qѽ#\x90-\v\x1c\xc1\xb8ܢ\xf6L\xdcjU\x10L\x94\xb9\x97>\x12]\xc1Q\x0e\xc9o\xaaM\xc1\xad\xe3\xfb_*4N\xc8\xd5\x1anI\xc5\xc0\x06\xa1*s'\x99k\xb8\x93p\xcb\n\x14\xb7\xcc\xe0\xab3\xc0Qڬ\x1ca\xd3X\xd0Վ\xc3Ξj\x9d\x1fj]6\xc1/\xaf\x10\x1eJ\xccz\x1bƍ\xe2[\x9eѶ\x80\xadҭ\xbe\xf0\xeaj\xdd\x03\x19߲\xaee\x86?HV\x9a\xbd\xb2N\xff\xaa\xca\x0e{\f\x10\xba}\xb8\x1b\f\xa8\x91\t\xa8\x91Z\xa9\f\xe6n\x9f=3n\x1dz#\x98\xe0\x00\xc1W\xd205<\xd24\x95\x01[iI\xbb\xf4\v\xb2\xfc\xf8\xa8\xfed\x10\U0008a135>+\xae`\x83[\xa51\x02W\xa3\x1b\xef:\xa3֎0\x86PR\x95]\xc3\xe3\x1e\x1d\x19Y%l\x90{n\xe0\xedOPpYY\\\x8f\xa0M0\xd8\x13\x85\xc0\xf8\x15\x98G\xf5\xd1xV-\x90\xef\xfdİ\x0e\x11\x9f\xf7h\xf7\xa8\xa1T\xb5\n\x8e\xacr\xcb\x05\x829\x1a\x8bE\xe0x\xad\xf86\x81\xfa$\x14B\x04\x10\x066\xc7\x1a\xe7\xf1:\xddy\xcb6\x02o\xc0\xeaj<\x9d'\xc3F)\x81l\xa8\x84\x87t\xf8\x82\xc6\xf2l\x81\n\x97C2\xf8Q\x11\"\xe8\xf0\x03\xad-B\x87M+k\x96=!\xb0\x9a\x1a\xeep\x10\xa2C\xc4\x1e\x05\xe0\xbf%\xbcw\x9a+s\xfad\x8c-\x04\xcd\xc5Q\x90\xb6\x94\n\x84\x92;\xd4~6w*)K_^\x85\x9c\x1e\xf13\x88\xe9\a\xd2\xf6\x92^m;:tc\xc8\t\xc2\xed\u06dd\xf7\xf0\x1a\xf6p\x03w\xd2\xf9-\x81\x1et#\u09db?\x1f\xfa\xad\xa8\f\x05\x89\xa5\x92+:*ױ\x99<\xb1\x13A*\xdd\xe3\xc8\x18\xb5fR?a\"\xd8Gw\x92\xf8\xf1\xfe\x8eC\xb0\f\xf3:\xc6I\x91yfq\xc73(P\xef\xe6\x0e\x8en+\x9d~OC!Q\xeb\xfav\xa2\x84\xa5\x1d\xedu\v\xaa;\x1a\x82뷕۹\t\xbdjf/v\x9d\b\xc8Ow]^\x11\x1d\xb1d\u007f,R\x97\xe59ݥ2q\u007f\x82\xc6?\x81\x17\xe3\xb3\xdf#\xe6OȂQ\x88\xf4\u007f\xdd1G\x02\xfd\u007fP2\xae\x13\xf6\xf0;\xba\x1a\x15\xd8\x1b\x1b\xa2X\xddi\xdc\f܀\xe3\uf049\xf1UOdq\xca\xe9\x16\x14\xfe Wۑ\xc5r\x05\xcf{e\xfc\x99J\xa1\xd9E\x90\xdc\xc0\xe5\x13\x1e/\xafFz\xe0\xf2N^\xfa\x03\xfedu\xd3X\vJ\x8a#\\\xd2\xd8\xcb\xef1\x82\x12%1\xa9\x1b]A\xa7\x9a\xcaΗ\xac-\x017\xb0\xb9wuf\xee\x1c\xd6IrX*\x13\xb9M\x9a@\xe5^\x19\xeb#\x8b=\xb3\xf4\x94(\x16x\x19\n\xd1+`[\u007f\xf3\xadt}\xa7\xe9\xd4\xde \xe0\xea\xb8f\xe65\xaccc\x13\x11\xf3@\x9dcu\xd9\xee`\xafO/\xfdE'M\xc222.\x16\xe1\x96Zeh̼\x88$h\xeb\x85 a\x13 dށ\xf1\x17\x86\xf3Aɺ\xa5\x1b\xa4\x8eH'\x9a\xf2\x1f\xbeu\xa2\x97n\xf3\xbb\u007f/\tߩx\x01\xed٢`Û\xf1$\x14o\xfd\xc8z\x9b\x04@\xde5л\x8a\xb6z\xba\x05\x19\x04\xe9\xf7pL\x17\\\xde\xd1\x04\xf0\xf6ŏ\xf5FI\xe29\x86\xfbm=\xb6%z\xf3\x81vo\xaaE\xa4(r\xaf\xb1ǹq\x9c\xdb\x19\x8a\x89 \xa5\xb2\xddp\x82\x83[\xaa\xfc\x8d\x81-\xd7\xc6v\x11M\x15\x8aja\xf7\xb7\xedT\xcfI~\xd0\xfa,\xc7\xe9\xb3\x1f\xd9\td\xed\xd5s\x9d_0y\x15\x1bkt)\x84\xc0\xb7\xc0-\xa0\xccT%)\xfc\xe2\xb6:M\xe1Y\xe0\x15t2\xc9\xd2\x14\x84k(\xab\"\x8d\x00+\x92:.g\xe34\xdd\xee\x1f\x19\x17\xaf\xc16;\x95\x86\x11k=\xb6\xd5\xf9\x18\xddD\x91\x82}\xe3EU\x00+\x1c\xe9Sݞ\xad\xcf\xe2\xe8q\xbc\xc9\xe5 \xb8t\x8cX\xe56U)Ц\xeeH\x9f\xb5ᶉ\xe196\as\x90\x02%\x81\xc1\x96q1qy>n'\xd1\xf6\x14_#(\x8b\x97s\"\xd2&_\x11)\x12\x02\xb1\x89\xc6⼶.u\xba\xa9x\xaf1\xcd<[\nJ\xd7\xe6Y\xa9\xb9\x93%\xf5\xd2\x16Z\x101&\x8f?L\xb4Q\xfba\xa2-\xb4\x1f&\xdad\xfba\xa2-\xb7\x1f&Zh?L\xb4\xba\xfd0\xd1~\x98hs\xdd\xe6\xb4\xf5\x12F\xfe\xc5\xc9ď\x8bX$\\Oϡ8\x03?dS\xdc\xfa\xd7'\xa9\x19\x96w\xf1Q\x91\xac\xe0\xf0\xaceE/rb\x12\xd0&]\xb4GI\x93r\xe96H-\xde>\x81~!\t\xf3;\xb2oS\x12~\x96\xd2|\xfay\xa6M\x9aM\x9dh\xaa\xeaI\"t\xa8_\xf68\xb3\xb7\x9bC\xd2\xcf\xd7!;\xb7\xc6\xf4\uf783\x9a\x90\x8a\xb3\x90\x803\x9f\x98;G\xaf\x81\xeb\xd1'\x98\xee%\x8c\xfe~\xe8e\xb1\xf8\\\x06QN{\xc4q\x17\x19\xb2\xf4\x8c#\xb2\x1e\xf2Q\xccQf{\xad\xa4\xaaLpk\x1c\xf4w\xe4]\x85\x1b\x17\xca6\x89\xbd\xbd\x88\xc0|\v{UE\x12Cgh\xb7\x90&4\x9d\x1c\x14\xae\xc2в\xc3\xdbu\xff\x17\xabB\xaa\x10\xecɊi\xde\xffJK&:;\x85\xa8\x9f\"4qF\x9dzg\x96\x9e)\x9d\x9e$4\x9f\xd5sJj\xd00\xf1g\x12\xe8rBP\x8a뼐\xfcsF\xcaOb\xba\xe7w\xdf\f\xa6$\xf5\x9c\x95ʳ\x98\x11\x99\x98\xc0\xd3O͙\ayB\xdaN\x12q\x96StNN\xcc\t\x890\xb3\xebHNlj$\xda\xcc\x02\x9eL\u0099K\xafY\bˍSoғjfAS\xc2\xcdr*\xcd\xcb%̾\x84\x130\xadj\x16\xd3a\x16\x9d\x84y\xfc\x16\x13^NIsY\xa4ؙ)-M\xca\xcaļ\xa7&\xb2\xf4\x13U&\x80\xa6\xa4\xafL\xa4\xa7L@\x9cMZIMJ\x99\x80\xbdp\xec\xceJ\xc9̏\xf1\x97аx\xbe\x89\xbf\x95D\x9d\xbb0\xa5{\xe6⒋\xf2y\xd0\xdd\U00072d9a\xe6\xcdϘ\xe5\xc9\xed\xfet\U000f3a04奠\xfb\x8c\x03ϣ^\xb3\xdd\xe3\xb1y\xd7\xfa\x9b\xa2w^\x9b#A\xfa\xfc\xa5\x11\xcf\xf5\xc0\x88f\x06\x9eQ\b`1\xe1\x1a\xad<\xf3\x8f\xf93\xb5B\xa7\xf3݆\v/vÛ\xff+/\xc1\xf4\x94-\x16\xf2\xb5{,\x1c\x94\xfa\xe9\xef\t\xfe\u05fc\x81\xe8mY\xfa\xf6\x97\n\xf5\x11\xd4\x01uk1,<\xa4\xf0\x1b\xcd8\xef\xa6\xde\xfaA\u007f\xf8\x12\x12\x03ù\xddp\xf0N\xfa#,\nv\x80#\xc1q{^4\xbcv\xea\xcd\xf9\x01\x13]\xe3\x91\x1fՌ\x8e\xfc\xbed{\xa6\xbeBx]\xd7\xe1t\xe7a\xf1\xd8~\x15\a\xe2|\x17b\x06dꫂ\xb4\x1b\xb8\xc5W\x04\xaf\xe5J,9\x13\xc9VT\xda+\x81\xd7x\x1dp«\x80\x13\x9c\x8a\xd3܊d2\xa5d\xff\xbf\x8as\xf1\x8a\xee\xc5k8\x18\xe7\xb9\x18\v \aY\xfd)\xf9\xfaI\xb7\xcb\xc9\x17,)\xb7\xc3\xcbw \xf3y\xf8\t\xf9\xf7\t\xb7#K\x98&\xe4ٟ\x96_\x9f@\xc3Wr>^\xc9\xfdx\r\a\xe4u]\x90E'dQrf\u007f>;\xbc\xaet\x8ez\xf66\"U\xd4f\x85l\xe0/\xf4\xe7\x1c\xc4\xe6\xeb\x127\xaeW\xcf4\x8d\x85\x94\x9b\xe7\xaf\x19\xfc\xc2e\xee\xf9ᄪs\x8e\xf7\xaeHZ\xc3\"\x1e\xa1o\xad\xb6P\x02\xcc߫\x18,\x99\xa6\xbaq\x9b\xa3\xbf\x9b5k\xf8\xc0\xb2\xfd\x00\xfa>\xea'l\x95.\x98\x85\xcb\xe6R\xea\xda\x03w\xff\xbe\\\x03|Tͭ_\xb7\xa4\x84\xe1E)\x8e\xce\x0f\x88\xc0\xbc\xec\x828O \xa2\xc2dB\xbd\xaaP\xc0g\xc1\xf7{\xe8\xf7\x8e\xdcfֵ\x8bj\xb8&\xee\xf80y\x84\xfb\xafd\x9dPŔ\xac\xad\x1e\x13\xec\x8f\xda\xfb\x1b\x16\x97\xf9\xf9\xe5\xef5\x8dU\x9a\xed\xf0W\xe5K\x90-Ѡ\u07fbW\u007f.h\x8d:Ϡ~\x86\x12;MC1\xb4\x01\xb06}hT\b\xcba\x19S'3;\xd1Z\xb1\xb0\x98\xc7\xc7_\xfd\x02,/p\xfd\xbe\xf2\x17\\\xab\x92i\x83\x8e\x9a\xf5\xc2\xfc\xa0\x8d\xfb߽z\x8eE9TX\xf3\xcfC\xbc5R\x8a\x12]U\x9f\x84\xfd\xa1WP\xad&ђ\x88~\x8d\x8f\xea\xb8h\x1d&\xf9\xdd\x1e\x95\xd0)8\x9d\x9a\x92\x14\xbc\xa0'F/[\xf1hJ\u007fOUݣJs\xcbu\xf7|A\xbaPe3$\xbaU\x9a\xca\x15\x85buT\xde\xe7\xac\xd2{ts\xdaޘ6\xf7\xb1杵\xce\xe0\x8c\x19a}\x0fu\x11@\xad߭\xb2L\x80\xac\x8aM4\xa2\xe4\xd6\xd0\f!\xb4for}\x82\xd1\f\v=ѹ\xb4\xb8\x1b\xcd7\xb9\xeaې\xa6t\xf6\xaa\x1b\x00\xe9\xab6U\x96\xa11\xdbJ\x88c\x93'\x95H\x82hhꥉ\xf2\x91qq>E\xfc\xe8\x189&N\x98SY\x1f*c\xa0\xcc\xc3֎\x1e[>\x8f\xf04\x8a\x04f\xf4\xca\x02\xcfS\xe1v<\x82\x8a\xbf꼓\xd0Д\a|f\xa6ex\xcc\xdel\xc1\xf9\x91\xe4\xf09h\x98\x03\x1eP\x82\x92\x94\aGU\xb2|\x81\xe2\xe1\x98\b\xd4.\x94\x90hW\x95B\xb1\xbc>\xfej\xd3.\x14\xb5}\xa4\xc3]\x1fP\xbf130\x9b\x82\x8f\x11\"\x8c\xad-ok\xdd@\xce,\xae\xa2@\x93\f\x83\xa8&\xce\f\xef\x9f\x02\xc9\xda\xec\xf6\xe1nj\xe4\x84\x04\xb7J+ƿQy\xd1\xefT\\㕥j\xac\xf1\xcafU\xd5P1E\x16ת\xaa\x17_&\xed\xd5\xc5Z\x88\xd4\xc9\xdb\a\x940\\\x97\xdb\xf4\x19\xc3\x05\x1a\xc3vu\x11\xc4gg\x9e\xedP\"y\a\xb1\xb0\xbc\x8f\x9f\xb4\x19\xa6\xfd\x12\x80>\xd0\xcb2[\xb10A\x9d \xd3\xe9\xf5&\xe6T\b\xb5\xf3\x85Ry]&\xba\xb6[O\xa4ɷ\x92\xeb\x14;\xf7C\xd3\xd1ц\xeeh\x88\x11mYo\x14|ǝ\x91蘴cz\xc3v\xb8ʔ\x10H\xbav\x8c\xd7kn\u0590\xc7\xfb\x05\x99Y\\\xda\xc7n\xdf\x10\x10\xf4\xdc\xf6\x15t\x98\xcf\x15\xa3*ϖkl˦\x8f\x10R4\xf1Iv\xad\xa7B\xb4\xc0\xf8\x18\xd3n\xdfz\x83\x05\xbd\x1a\xdc\xccPo\xfc*xJ\xf1\xa0O\xc1~S\xfa\n\n.\xdd\u007f\x9cSL\x11\xbbz\xf0I\xf8Sm\xcb\x05\xbc\xef]\x9f\xe69E\xc7\xca\xc4zCL\xf9q\xf1\x14\xfa\x15|±\xdb\xe1\xb3\xe21\xa7\x18u\xac\xaa\xba\xebr'\xef\xb5\xdai4\xe3]\xb5\x82?3n\xb9\xdc}T\xfa^T;.[{\xe3\xa4\xce\xf7L[΄8z|b\x88r\xc9\x04\xff+\x97\xbbw[\x8b)\xb3-\x8cX\x9e\xb2Q̑\xdf\x12\x10\x9e\xfa\xe1=\xbaCy\xd2m\x89\x8bL\xe0\xc0\x92Ԅnm\xf4\x8dK/唫\xbfQ\x95\xed\xa9\xc9V\xcdFD\xbe\x9es\r\x9f\x94\xc5\xfaR\x87\xf7a\xba\x83\x05\x8d]\xe1v\xab\xb4\xf5\xc1\xbe\xd5\n\xf86\xb8A\xb1\xe8\x0e\xe3\x82.\xa5}\x01w\xe0\xb6\xcd\xcbiw&E84)\x18\xaarW\xb0\xa3\xcf\xdbfY\xe6\xbcl\xbc6\x96\x89\x88\xee\xfe\xae4H\xf27\xdd\xce\xc2\xfcO\x11\x1bsD\xf0\xbbn\xff\xa6xFsr\x138O9zW\xe3ϭ\xe8)\x0e\xf4\xda\x02%Jr\xf0\xd5\xd9C\x95A\x12\x83\xb2D\t\xcc\x04|\x12\x1e\x95γu.4i\x99\xb6\xa9\x1e\xd3C\xaf\xf3\x82\xb3D\x90\xe3\xf8>\x84ȯ\u007f\\{;\xfcs.W`\xb8\xac\xff~\x89\x8f+{Q0·\xd2HA\xba\xe8\x1d\xf6\xc8\xfb\xe9\xf9:}\xf4\xff\xb6nΡ9=?\xa4\xd8\xcb_\a\xdd\a/\x14\xa8L\u007f\xd3%ظ\x11z\xfc\x81o\xfd\xb5z\xe6\xb0\xfe\xe3\xdf\xfd\xe5\xc1!\xc9\x1e{3k\x8a\x91\x95\xd5\xd8T\vE\xf9\xef\x05:\x1b\xc9 \xf6\xad\xbc7'\x99\xf3\x87\xf3\x1cԗ\xf4N\xeb?\xad\xf32>\xdb\xe1<\xbf\xf4՜җ]\xdd3\xa3?籴\xc7\xfe\x1c\xbaE\xbc\xd2\x00!\xe2\x97F\x96\xd1x\xaa\x8b~i\xc7-\xadq\x9c\xa8\xf8?pU_\xc81\x8d\x9e\x03\xa3\x8f\xa4@\xf3\xce\xde\x0e3\x85/m$\x9ce\x19:q\xfd4\xfc\x13Z\x97\xfe\xefQ\xd4\u007f%\x8b\xfe\x99)\xe9\x8f[s\x03\xff\xf5?\x17\x10\xaeZ\xbe\xd6\u007f\x0e\xcb}\xfc\xff\x00\x00\x00\xff\xff\xed\xa36\x94nl\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4YKo#\xb9\x11\xbe\xebW\x14f\x0f\xbe\x8cZ\xb3\xc9!\x81.\x81F\x93\x00\x83x\xd6\xc6\xc8q\x0eI\x80\xa5Ȓ\xc45\x9b\xec\xf0!\xad\x12\xe4\xbf\aŇ\xba\xd5ݲ\xe4A\xb2ˋ->\x8aU_\xbdٓ\xe9t:a\x8d|F\xeb\xa4\xd1s`\x8dğ=j\xfa媗\u07fbJ\x9a\xd9\xfe\xfbɋ\xd4b\x0e\xcb༩\xbf\xa23\xc1r\xfc\x84\x1b\xa9\xa5\x97FOj\xf4L0\xcf\xe6\x13\x00\xa6\xb5\xf1\x8c\xa6\x1d\xfd\x04\xe0F{k\x94B;ݢ\xae^\xc2\x1a\xd7A*\x816\x12/W\xef?T\xbf\xab>L\x00\xb8\xc5x\xfcI\xd6\xe8<\xab\x9b9\xe8\xa0\xd4\x04@\xb3\x1a\xe7\xb0f\xfc%4\xce\x1b˶\xa8\fOwU{ThM%\xcd\xc45\xc8\xe9\xea\xad5\xa1\x99C\xbb\x90(d\xb6\x92H\x1f#\xb1U\"v\x9f\x89\xc5u%\x9d\xff\xf3\xe5=\xf7\xd2\xf9\xb8\xafQ\xc12u\x89\xad\xb8\xc5\xed\x8c\xf5?\xb4WOa\xedTZ\x91z\x1b\x14\xb3\x17\x8eO\x00\x1c7\r\xce!\x9en\x18G1\x01ȘEjS`BD-0\xf5h\xa5\xf6h\x97F\x85Z\x9f\xee\x12踕\x8d\x8f('Y \v\x03E\x1ap\x9e\xf9\xe0\xc0\x05\xbe\x03\xe6`\xb1gR\xb1\xb5\xc2\xd9_4+\xffGz\x00?9\xa3\x1f\x99\xdf͡J\xa7\xaaf\xc7\\YM:z\xec\xcc\xf8#\t༕z;\xc6\xd2=s\xfe\x99))NZ\a\xe9\xc0\xef\x10\x14s\x1e\x8c\xb6e,\x1e?\x97ț\x1c(\xfb[ƪ\x82E\xf6\\\xb3\x81\x0f \xa4\xa3\x02\xc0E\xa2C\xb0\xa8<\xa3\xf59x\x1b\xde$>7z#\xb7C\xa1\xbb5\xcd%\x8b\xb9B\xba\x87\xdc2\xdeD\xa1\x89\xac\xa3\xb1f/\x05\xda)\xf9\x87\xdcH\x9e9\t6e\xae\x8dD%\xdcP\xd2\v^\x16E\xb1(ȫ\x99\xba\xa2\xc3\xe5ic,\x8d\x99\xd4ɂ[\x021\xd8\xd8:\xa7T\xedQ\x8bS5rƍ\x89Qˡ\x80\x83\xf4\xbb\x14\x0e\u0558\xdf\xc1\xab\xbeG\xe3\x05\x8fc\xd3=ޟvH;S\x02Ep\xc8-\xfahm\xa8\xc8|Ȕ*\x80/\xc1ŀڏ\x13e\xc4B\xad\x9c~\xc1\xe3\x10h\xb8\xa6\xdc\\\xc2\\g\xf9\x8eJ\xe7°\xc5\rZ\xd4~4\xa8Sgb5z\x8cq]\x18\xee(\xa4sl\xbc\x9b\x99=ڽ\xc4\xc3\xec`\xec\x8b\xd4\xdb)\x01>\xcd\x1e4\x8bm\xc5\xec\xbb\xf8\xe7\x82\xc8O\x0f\x9f\x1e\xe6\xb0\x10\x02\x8cߡ%\xadm\x82*\x86֩o\xde\xc7\x1c\xfb\x1e\x82\x14\u007f\xb8\xfb\x16\\L\x93<\xe7\x06lV\xd1\xfa\x8fT\xa8E\xa6\b\xa2UҊ\xb1@\x99\x92\x94]gm\xa6X3f\x88c\x15fwP`\xa2\f2\x16Q_p\x18L_q\xb3\\\xec^\xf1\xb1RHK-$\xa7B\xec\xdc7J\x83!\xce\xea\xed\x11\xc1\xfa\x15\xf8\xa5\x880.x\x12 \xe7\xc3+\x1c?t\xf7\xb6mY\nO9\xc79\xf4T@9\xd0H9\x90\xd9!r1(p\xa35y\xa37\xc0N\xa1\xee\xce\xf5c\xfc\x1b#\xc4:\xf0\x17\x1c\x01~ \xcaǸ\xb1`\x9c\x8e\x11/\xc1a\f\xbe\xd7\u0600\xeb6\xce\xd9\x12\xed-\xbc,\x17\xb4\xf1\x94&\x19,\x17\xb0\x0eZ(,\x1c\x1dv\xa8\xa9C\x90\x9b\xe3\xf8]4\x9e\xeeW\x05\xd5Xa\xe4\x1a\xbf`;.C\x8a\xe1sX\x1fGj\x82\x1b\x84l,n\xe4\xcf7\b\xf9\x187\x16\xc0\x1b\xe6w \xb5\x93\x02\x81\x8d\xc0\x9f\x8a\xb5\v\x82\x9e\xf2\xffC\x8e\"ߠ\x9e\u05fc=\xb1\xf3\x16\x87/\x18_\xf1\x9fǼ\xed\x84B\xf9\x9d#\xffy-xɏG%ڟ\x1e\f\xfe\x94*,>\x92*Ϙy\x1e\x9ex\xa5R+\xcf\x16c\xceLu\x81\xb1\x16]c\xb4\xa0\xe6\xe9\xb6:\xade\xf9\u007fW\xad\x8d\xabuz\x1e\xe5zkE\v7\xb5*\xf1\x89\xe6\xcd\xcdJz\xb8\xea\xb6\x02f\xed\xa8Sl\xfb\x95\x9e\x8c\xbfH\x9b\xf2\xaeӧP?\xac!\xe8X\xa9Ō_\xc1\xdf5|\xa2ޖ\xb2\x93\x98\x13\xdfv\xcc\x00\xa4\x03m\x0et\xbcC/\x92\x00\xa3S\xbe\xa6n\x8di\x91\x9b\xe1\xb8t\x90JQƶX\x9b\xfdhƦBӢ:\x02sd:\xfb\xdfT\x1f\xaaw\xbfZ\x17\xa4\x98\xf3\xd4Ԡ\xf8\x8a{9|\xe5\x19\xa2{?8Q\x1c\xff\xe4\x0e\xf4\xe3\xc7\xd2,\xcfl\xde\xf6\xe3\b\x18\x1b\xa9\xa8\x16\x1c\x89\x13m\xc50|\x8f\xfc\xb8\xba\xbfs\xb1\x84G\xed\xc7ʾ\x03Z\x8c\x1d\x13\n\xaa\xe2M~\x97\bΣ\x1d1\x80\x93\xf6\xa2\xceA\x19\xbd\xed9N\x1a\xf9\x95\x82*\xb4dPƂ@O\xa9Io\x81\xef\x98\xdeb\xfb\n\x95\xf9\u007f\x9dS2\x9f\x9eʹ\x16\"\xf5%\xf3\xb8I\xa3Or\xacL\x1f\xbc\x00\xb7\x9b\xc7_\u007f\v\xf7E\xb3\x17ۜ+\xb8\x0f\xf6\x97,M\xa0N}\xfb\"\u070eooo\x87\xcf\xcd7 \xf1ַ\xf0W\xde5\xe0\xc0\\\xfb*\xfe\xeb\xe1PS\xb5z\xb5\x04\xfe\x92v\xa5\xe7\xc3|\x04\xd8\xda\x04\xff\x9agލ\x19t~\xee\u007f\v\x8f\xf1#Ƶ\"\x83\xf6\x14\x8d\xf0`\xa9\x95l_\xc5bP\x18\xcb-\xb7?/-z\xdfZ\xbak\xc3/17\xc85\x9ak\a\x93)_v\xf4\x9aA\xee΄\xf5\xe9\xa5x\x0e\xff\xfeϤMה\x13\x1b\x8f\xe2\x87\xfeǵw)d\x94/d\xf1'\xa7:&}\x1d\x84\xbf\xfdc\x92\xaeB\xf1\\>i\xd1\xe4\u007f\x03\x00\x00\xff\xff\x1d\r\x93\v\x97\x1c\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4\x96Ms\xe36\x0f\xc7\xef\xfa\x14\x98}\x0e{y$\xefN\x0f\xed\xe8\xd6\xcd\xee!\xd36\xe3I2\xb9tz\xa0I\xd8\xe2F\"Y\x00t\xeav\xfa\xdd;$%\xbf\xc8v6=\x947\x91 \xf0\xe7\x0f\x04Ī\xae\xebJ\x05\xfb\x84\xc4ֻ\x16T\xb0\xf8\x87\xa0K_\xdc<\xff\xc0\x8d\xf5\x8b\xed\xc7\xea\xd9:\xd3\xc2Md\xf1\xc3=\xb2\x8f\xa4\xf13\xae\xad\xb3b\xbd\xab\x06\x14e\x94\xa8\xb6\x02P\xceyQi\x9a\xd3'\x80\xf6N\xc8\xf7=R\xbdA\xd7<\xc7\x15\xae\xa2\xed\rRv>\x85\xde~h\xbeo>T\x00\x9a0o\u007f\xb4\x03\xb2\xa8!\xb4\xe0b\xdfW\x00N\r\u0602\xc1\x1e\x05WJ?\xc7@\xf8{D\x16n\xb6\xd8#\xf9\xc6\xfa\x8a\x03\xea\x14xC>\x86\x16\x0e\ve\xff(\xaa\x1c\xe8sv\xf5)\xbb\xba/\xae\xf2joY~\xbaf\xf1\xb3\x1d\xadB\x1fI\xf5\x97\x05e\x03\xb6n\x13{E\x17M*\x00\xd6>`\vwIVP\x1aM\x050\xf2\xc82kP\xc6dª_\x92u\x82t\xe3\xfb8Ldk0Țl\x90L\xf0\xb1\xc3|D\xf0k\x90\x0e\xa1\x84\x03\xf1\xb0\xc2Q\x81\xc9\xfb\x00\xbe\xb2wK%]\vM\xe2\xd5\x14\xd3$d4(\xa8?ͧe\x97\x04\xb3\x90u\x9bk\x12X\x94D\x9eD\xe4\xb8\xd6;\xa0#\xbe\xa7\x02\xb2}\x13:ŧ\xd1\x1f\xf2µ\xc8\xc5f\xfb\xb1\x90\xd6\x1d\x0e\xaa\x1dm}@\xf7\xe3\xf2\xf6黇\x93i8\xd5z!\xb5`\x19Ԥ4\x81+\xd4\xc0;\x04O0x\x9a\xa8r\xb3w\x1a\xc8\a$\xb1\xd3\xd5*㨪\x8efg\x12\xde'\x95\xc5\nL*'\xe4\fm\xbc\x04hƃ\x15\x98\x96\x810\x102\xbaR`'\x8e!\x19)\a~\xf5\x15\xb54\xf0\x80\x94\xdc\x00w>\xf6&U\xe1\x16I\x80P\xfb\x8d\xb3\u007f\xee}s:g\n\xda+9\xe4g\x1a\xf9\xd29\xd5\xc3V\xf5\x11\xff\x0f\xca\x19\x18\xd4\x0e\bS\x14\x88\xee\xc8_6\xe1\x06~I\x98\xac[\xfb\x16:\x91\xc0\xedb\xb1\xb12u\x13\xed\x87!:+\xbbEn\fv\x15\xc5\x13/\fn\xb1_\xb0\xddԊtg\x05\xb5D\u0085\n\xb6\xce\xd2]\xee(\xcd`\xfeGc\xff\xe1\xf7'Z\xcf.H\x19\xb9\xd0_\xc9@*\xf3\x92\xf6\xb2\xb5\x9c\xe2\x00:M%:\xf7_\x1e\x1ea\n\x9d\x931\xa7\x9f\xb9\x1f6\xf2!\x05\t\x98uk\xa4\x92\xc45\xf9!\xfbDg\x82\xb7N\xf2\x87\xee-\xba9~\x8e\xab\xc1\nOW2媁\x9b\xdcbSQ\xc7`\x94\xa0i\xe0\xd6\xc1\x8d\x1a\xb0\xbfQ\x8c\xffy\x02\x12i\xae\x13ط\xa5\xe0\xf8\xef07.Ԏ\x16\xa6\xf6}%_\x17\x8a\xf6!\xa0N\x19L\x10\xd3n\xbb\xb6:\x97\a\xac=\xc1Kgu7\x15\xed\x8c\xee\xbe\xc0\x9b\x93\x85\xcb\x05\x9dơM\xceW\xae\x1e\x1er\xee,\xe1\xec\x16\xd6p\xd6s_璛\xe1\xbf$S:\xf1\xc8FG\"trԟեMoe\x81D\x9e\xcefg\xa2\xbed\xa3\xfc\x04P\xd61(\xb7\x1b7\x82tJ\xe0\x05)\x95\x81\xf61\xf5\x194`\xe2\x19\xbf\x11\xcb\xf1\xbf$\x90\xd7\xc8ܜ\xd9Y\xc1ႦW\xb2\x93Fz^\xa8U\x8f-\bE\xbc\x92YE\xa4v\xb3\xb5\xfc\xcf\xfa\x06\x82e\xb2\xb9\x94\x83\xfd\u007f\xfa\x9bIȸ]\x1c\xce#\xd5p\x87/\x17foݒ\xfc\x86\x90\xe7W>-.\v\xbd\xfdc\xe0\r\x94.^ʳIN\xfd\xce\x1cQd\xf1\xa46\xc7\\9\xae\xf6\xfd\xbb\x85\xbf\xfe\xae\x0e\xf7Zi\x8dA\xd0\xdc\xcd_i\xefޝ<\xb7\xf2\xa7\xf6\xae\xbc\x8c\xb8\x85_\u007f\xabJ(4O\xd3\xeb)M\xfe\x13\x00\x00\xff\xff--\nM\xde\n\x00\x00"), - []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4WO\x93ܦ\x13\xbdϧ\xe8\xf2\xef\xe0_\xaa,\x8d]9$5\xb7d\xed\xc3V\x1cǵ\xe3\xec%\x95\x03\x83z$\xb2\b\b\xdd\xccz\xf3\xe9S\r\xd2\xfc\xd1hfׇp\x134\xcd\xe3\xf1\xfa\x81\x16UU-T0\xf7\x18\xc9x\xb7\x02\x15\f~et\xf2E\xf5ÏT\x1b\xbfܽ[<\x18\u05ec\xe0&\x11\xfb\xfe\x0eɧ\xa8\xf1=n\x8d3l\xbc[\xf4ȪQ\xacV\v\x00\xe5\x9cg%\xdd$\x9f\x00\xda;\x8e\xdeZ\x8cU\x8b\xae~H\x1b\xdc$c\x1b\x8c9\xf9\xb8\xf4\xeem\xfdC\xfdv\x01\xa0#\xe6\xe9_L\x8fĪ\x0f+p\xc9\xda\x05\x80S=\xae\xa0\xf1\x8f\xcez\xd5D\xfc;!1\xd5;\xb4\x18}m\xfc\x82\x02jY\xb4\x8d>\x85\x15\x1c\x06\xca\xdc\x01P\xd9\xcc\xfb!\xcd]I\x93G\xac!\xfeen\xf4\xa3\x19\"\x82MQ\xd9s\x10y\x90\x8ck\x93U\xf1lx\x01@\xda\a\\\xc1'\x81\x11\x94\xc6f\x010\xec=ê\x86\xdd\xedޕT\xba\xc3^\x15\xbc\x00>\xa0\xfb\xe9\xf3\xed\xfd\xf7\xeb\x93n\x80\x06IG\x13838\xc1\f\x86@\xc1\x80\x00\xd8\xefA\x81r\xa0\"\x9b\xad\xd2\f\xdb\xe8{\xd8(\xfd\x90\xc2>+\x80\xdf\xfc\x85\x9a\x81\xd8G\xd5\xe2\x1b\xa0\xa4;P\x92\xaf\x84\x82\xf5-l\x8d\xc5z?)D\x1f0\xb2\x19Y.\xedH\\G\xbd\x13\xe0\xafeo%\n\x1aQ\x15\x12p\x87#?\xd8\ft\x80\xdf\x02w\x86 b\x88H\xe8\x8a\xceN\x12\x83\x04)7젆5FI\x03\xd4\xf9d\x1b\x11\xe3\x0e#CD\xed[g\xfe\xd9\xe7&aH\x16\xb5\x8aG9\x1c\x9aq\x8c\xd1)\v;e\x13\xbe\x01\xe5\x1a\xe8\xd5\x13D\xcc<%w\x94/\x87P\r\xbf\xfa\x88`\xdc֯\xa0c\x0e\xb4Z.[\xc3cQi\xdf\xf7\xc9\x19~Z\xe6\xfa0\x9b\xc4>Ҳ\xc1\x1d\xda%\x99\xb6RQw\x86Qs\x8a\xb8T\xc1T\x19\xba˅U\xf7\xcd\xff\xe2P\x86\xf4\xfa\x04+?\x89̈\xa3q\xed\xd1@\xd6\xfc\x95\x13\x10\xd5\x17\xc1\x94\xa9e\x17\a\xa2\xa5Kع\xfb\xb0\xfe\x02\xe3\xd2\xf90\xa6\xec\x17\xe5\xec'\xd2\xe1\b\x840\xe3\xb6\x18\xcb!f\xe5INtM\xf0\xc6q\xfe\xd0֠\x9b\xd2Oi\xd3\x1b\xa6Q\xccrV5\xdcd\xa7\x81\rB\n\x8dblj\xb8up\xa3z\xb47\x8a\xf0??\x00a\x9a*!\xf6eGpl\x92\xd3\xe0\xc2\xda\xd1\xc0\xe8d\x17\xcekR\xea\xeb\x80ZNO\b\x94\x99fkt.\r\xd8\xfa\b\xeaP\xf9\x03\x81\xf5I\xe6\xf9\xca\xcd\xe0Tl\x91\xa7\xbd\x13,_r\x90,\xffةS\xa3\xf9?\xd6m-^A\x03\x90\xe2\x1e\xdf\xd5g\x19/c\x80Y\xf5\xce\"\x19E,4\b\xafb\x05bRǘΗ\x96\x86.\xf5\xf3\vT\xf0s\xc6\xfcѷW\xc7o\xbcc\x91\xfbՠ{oS\x8fk\xa7\x02u\xfe\x99\xd8[\xc6\xfe\xb7\x80\xb1\\\xa5WC\xc7\x1by\u007fK\x9d\aޡx9^\xde\xc5\x10p\x87\x94\xecEd\x87\xa0\x17\xae\xf7\xa2Mܬo\xbf\x85\x9e\v\xe1W\x0f\xe0BI\x8e-_\xbd\xcf\xebK.\xefQ_2\xa5\xdcG\b\xf2\xa4\x89\x0e\x19\xe9`\x8d\x8f\x86\xbbٌ\x00\x8f\x9d\xd1]\x9e\x98\xc5)\xaeK\xe4\xb5\xc9\x1e\xf6\xed\xf0\xa5\xa6Mę\x02\xa9r\xe1\xcct\v\xf8\xb3\xee\vNti\x81jp\x87\x17\xb9\x19+N\xf4\r~\x96\xe3G\xaau\x8a\x11\x1d\x0fY\xf2\xfd>\x9d\xf0RC\x1b]\xe0\xf7\xbb\x8fϸ\xda\xfbCd~\xc1*\xe3\n\x9a\x10\xb1\"\xd3ʫD\xc6\xc4ײߜ\x93Q\xda\xe9+锨\xd9\x13ů\xc1\x94\x82y\x06\xe2\x87}`1_t\xe5b\x9d\xbe\x03sB\xa4\xfch\xd1j\xfa\\\x92\xb6Ah\xd0\"c\x03\x9b\xa7r\x8b<\x11c\u007f\x8e{\xebc\xafx\x05r\xe1Vlfd$ou\xb5\xb1\xb8\x02\x8e\xe9\x92\xcaf7\x1e:E3ex\xb2\xe7\xcf\x123'\x8c}1^U\x06\\\xf4\xfa\n>\xe1\xe3L\xef\xe7\xe85\x12\xe1y\x19]\xdc\xc9l\x11\x9cu\x92\xbc\x8a\x9a#\x96\x86\xc7\xf6\xd0s(\x19\xa55\x06\xc6\xe6\xd3\xf4\x0f\xe6ի\x93_\x92\xfc\xa9\xbdkL\xf9\xf9\x82?\xfe\\\x94\xac\xd8\u070f\u007f\x1a\xd2\xf9o\x00\x00\x00\xff\xff\xdb\xd9+\xab\xf6\r\x00\x00"), + []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4WO\x93ܦ\x13\xbdϧ\xe8\xf2\xef\xe0_\xaa,\x8d]9$5\xb7d\xed\xc3V\x1cǵ\xeb\xec%\x95\x03\x83z$\xb2\b\b\xdd\xccz\xf3\xe9S\r\xd2\xfc\xd1hfLJp\x134\xcd\xe3\xf1\xfa\x81\x16UU-T0\x0f\x18\xc9x\xb7\x02\x15\f~et\xf2E\xf5\xe3\x8fT\x1b\xbfܾ[<\x1a\u05ec\xe0&\x11\xfb\xfe\x0eɧ\xa8\xf1=n\x8c3l\xbc[\xf4ȪQ\xacV\v\x00\xe5\x9cg%\xdd$\x9f\x00\xda;\x8e\xdeZ\x8cU\x8b\xae~Lk\\'c\x1b\x8c9\xf9\xb8\xf4\xf6m\xfdC\xfdv\x01\xa0#\xe6\xe9_L\x8fĪ\x0f+p\xc9\xda\x05\x80S=\xae\xa0\xf1O\xcez\xd5D\xfc;!1\xd5[\xb4\x18}m\xfc\x82\x02jY\xb4\x8d>\x85\x15\xec\a\xca\xdc\x01P\xd9\xcc\xfb!\xcd]I\x93G\xac!\xfeen\xf4\xa3\x19\"\x82MQ\xd9S\x10y\x90\x8ck\x93U\xf1dx\x01@\xda\a\\\xc1'\x81\x11\x94\xc6f\x010\xec=ê\x86\xddmߕT\xba\xc3^\x15\xbc\x00>\xa0\xfb\xe9\xf3\xed\xc3\xf7\xf7G\xdd\x00\r\x92\x8e&pfp\x82\x19\f\x81\x82\x01\x01\xb0߁\x02\xe5@E6\x1b\xa5\x196\xd1\xf7\xb0V\xfa1\x85]V\x00\xbf\xfe\v5\x03\xb1\x8f\xaa\xc57@Iw\xa0$_\t\x05\xeb[\xd8\x18\x8b\xf5nR\x88>`d3\xb2\\ځ\xb8\x0ez'\xc0_\xcb\xdeJ\x144\xa2*$\xe0\x0eG~\xb0\x19\xe8\x00\xbf\x01\xee\fA\xc4\x10\x91\xd0\x15\x9d\x1d%\x06\tRn\xd8A\r\xf7\x18%\rP\xe7\x93mD\x8c[\x8c\f\x11\xb5o\x9d\xf9g\x97\x9b\x84!Y\xd4*\x1e\xe5\xb0o\xc61F\xa7,l\x95M\xf8\x06\x94k\xa0W\xcf\x101\xf3\x94\xdcA\xbe\x1cB5\xfc\xea#\x82q\x1b\xbf\x82\x8e9\xd0j\xb9l\r\x8fE\xa5}\xdf'g\xf8y\x99\xebì\x13\xfbH\xcb\x06\xb7h\x97d\xdaJE\xdd\x19F\xcd)\xe2R\x05Se\xe8.\x17V\xdd7\xff\x8bC\x19\xd2\xeb#\xac\xfc,2#\x8eƵ\a\x03Y\xf3\x17N@T_\x04S\xa6\x96]쉖.a\xe7\xee\xc3\xfd\x17\x18\x97·1e\xbf(g7\x91\xf6G \x84\x19\xb7\xc1X\x0e1+Or\xa2k\x827\x8e\xf3\x87\xb6\x06ݔ~J\xeb\xde0\x8db\x96\xb3\xaa\xe1&;\r\xac\x11Rh\x14cSí\x83\x1bգ\xbdQ\x84\xff\xf9\x01\b\xd3T\t\xb1\xd7\x1d\xc1\xa1IN\x83\vk\a\x03\xa3\x93\x9d9\xafI\xa9\xdf\a\xd4rzB\xa0\xcc4\x1b\xa3si\xc0\xc6GP\xfb\xca\x1f\b\xac\x8f2\xcfWn\x06\xa7b\x8b<\xed\x9d`\xf9\x92\x83d\xf9\xa7N\x1d\x1b\xcd\xff\xb1nk\xf1\n\x1a\x80\x14\xf7\xf8\xae>\xc9x\x1e\x03̪w\x16\xc9(b\xa1Ax\x15+\x10\x93:\xc4t\xba\xb44t\xa9\x9f_\xa0\x82\x9f3揾\xbd8~\xe3\x1d\x8b\xdc/\x06=x\x9bz\xbcw*P\xe7_\x88\xbde\xec\u007f\v\x18\xcbUz1t\xbc\x91w\xb7ԅ\xc0dϮ{\x87\xe2\xf7x~\xa7C\xc0UY\xae\xc04D^\xb5ћ\xfb\xdbo\xa1\xf0L\xf8\xc5C:S\xb6c\xcb\xd7\xf3\xcb\x1a\x94\v~ԠL)w\x16\x82<{\xa2CF\xda\xdb\xe7\x93\xe1n6#\xc0Sgt\x97'f\x01\x8b3\x13ym\xb2\xcf};|\xa9{\x13q\xa6\x88\xaa\\\\3\xdd\x02\xfe\xa4\xfb\x8c[\x9d[\xa0\x1a\x1c\xe4*\xc7cʼn\xbe\xc1\xf3r\xfcH\xb5N1\xa2\xe3!K~\x03L'\\kz\xa3S\xfc~\xf7\xf1\x05\xe7{\xbf\x8f̯\\e\\A\x13\"VdZy\xb9Șx_\xf6\xa4S2J;~I\x1d\x135{\xa2\xf85\x98R0/@\xfc\xb0\v,\x06\x8d\xae\\\xbeӷbN\x88\x94\x1f6ZM\x9fT\xd2\xd6\b\rZdl`\xfd\\n\x9agb\xecOqo|\xec\x15\xaf@.\xe5\x8a͌\x8c\xe4=\xaf\xd6\x16W\xc01\x9dS\xd9\xec\xc6C\xa7h\xa6\f\x8f\xf6\xfcYb愱+Ƌʀ\xb3\xf7A\x05\x9f\xf0i\xa6\xf7s\xf4\x1a\x89\xf0\xb4\x8c\xce\xeed\xb6\bN:I^N\xcd\x01KÃ|\xe8ٗ\x8c\xd2\x1a\x03c\xf3i\xfa\x97\xf3\xea\xd5\xd1oK\xfe\xd4\xde5\xa6\xfc\xa0\xc1\x1f\u007f.JVl\x1eƿ\x11\xe9\xfc7\x00\x00\xff\xff:@\xbd\xf3\x1a\x0e\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4Z\xdds\x1b\xb7\x11\u007f\xe7_\xb1\xe3<\xa8\x991\x8f\x89\xdbi;|s\xa4\xa6\xa36\x915\x96\xad\x17\x8f\x1f\xc0\xc3\xf2\x0e\xd1\x1d\x80\x028\xcal&\xff{g\xf1q\xbc\x0f\x90\x944ur/6\xf1\xb1\xf8a\xbfw\xa1\xc5r\xb9\\0-\xee\xd1X\xa1\xe4\x1a\x98\x16\xf8š\xa4_\xb6x\xf8\xbb-\x84Z\xed\xbe_<\b\xc9\xd7p\xd9Y\xa7\xda\xf7hUgJ\xbc\u00ad\x90\xc2\t%\x17-:ƙc\xeb\x05\x00\x93R9FÖ~\x02\x94J:\xa3\x9a\x06ͲBY\xf38\xfa\x01\xed\xe4\xfa\x8b\x99\xdb\x1e\xd1~[aޞ\xc3\xf4\xee\xfb\xe0@\xcb\x1a[\xb6\x8e+\x95F\xf9\xf6\xf6\xfa\xfe\xcfw\xa3a\x00m\x94F\xe3Dr\xe8\xe1\x1bı\xc1(\x8cY}A\x04\xc3*\xe0\x14\xc0\xd0\x06\xab\bc\xc8#\x86 \x0eaIu\rZ\x94nȒ\xf4\xa9-0\tj\xf3\v\x96\xae\x80;4D&\t\xa6Tr\x87Ɓ\xc1RUR\xfc\xb7\xa7mI\xd7\xe8І9\x8cq\xe5\xf0y\xd7/Y\x03;\xd6t\xf8\x1a\x98\xe4в=\x18\xa4S\xa0\x93\x03z~\x89-\xe0ge\x10\x84ܪ5\xd4\xcei\xbb^\xad*\xe1R\xfc.U\xdbvR\xb8\xfdʇb\xb1\xe9\x9c2v\xc5q\x87\xcdʊj\xc9LY\v\x87\xa5\xeb\f\xae\x98\x16K\x0f]\xfa\x18^\xb4\xfc\x1b\x13#\xbe\xbd\x18a\x9d)F\xf8|x=!\x01\n\xb0 ,\xb0\xb85\xdc\xe2\xc0\xe8\xe4 \xdf\xff\xe3\xee\x03\xa4\xa3\xbd0\xa6\xdc\xf7|?l\xb4\a\x11\x10Ä\xdcbt0[\xa3ZO\x13%\xd7JH\xe7\u007f\x94\x8d@9e\xbf\xed6\xadp$\xf7\xffth\x1dɪ\x80K\x9fԐ\xc3\xec4i./\xe0Z\xc2%k\xb1\xb9d\x16\xbf\xba\x00\x88\xd3vI\x8c}\x9a\b\x86\xf9\xd8tq\xe0\xda`\"%MG\xe45Ʉ\xee4\x96$=b \xed\x14[\x11=\x14\xb9s6]^\x8c\b\xe7\r\x97\xbe\xacw\x9a.\x82\\p\x99\xecI\xd8\xe4\xc0\xa7&\x87\x19VΈ\x024S/\xdb\xef\x19F.\x1b\x1dl1\xa3pD\f\xf4I\xc5\xf1\xcc=n\x14\xc7\x1cl\xda\n\xaefA[)\xe3#\u007f\xd4I9?\x85>%\x9f\x05L+~\x06W<\x91\x81\xc1-\x1a\x94%&\xc7u*\x9d\xc9 \x1b&\x1as\x8cǕ\x02Nx\xf5,ⷷ\xd7ɓ'&F\xecn~\xee\x19\xfeз\x15\xd8p\x1f\xe8Ο}q\xbd\r\x87y\x9f\xe6\x140\xd0\x02Cb\xda\a\t\x10\xd2:d\x1c\xd46K\x91\xca' \xc37\x18w\xbc\x0e\x1e,\xba\xcaCh!\xde\x03#\xdf)8\xfc\xeb\xee\xdd\xcd\xea\x9f9\xd6\xf7\xb7\x00V\x96h}^\xee\xb0E\xe9^\xf7\xa5\x02G+\frJ\xfc\xb1h\x99\x14[\xb4\xae\x88g\xa0\xb1\x9f\xde|\xces\x0f\xe0Ge\x00\xbf\xb0V7\xf8\x1aD\xe0x\uf593\xd2\b\x1b\xd8\xd1S\x84G\xe1j1\r\xa6=\aH\xbd\xe2\xb5\x1f\xfdu\x1d{@P\xf1\xba\x1dB#\x1ep\r\xaf|Zs\x80\xf9+\xd9\xceo\xaf\x8eP\xfdS0\xedW\xb4\xe8U\x00\xd7\xc7\xe1\xa1\xd1\x1d@\x06\xcb3\xa2\xaa\xf0\x90UM?\x1fT\xc8U\u007f\v\xca\x10\a\xa4\x1a\x90\xf0\x84Iz\xc1Q\"\x9f\x81\xfe\xf4\xe6\xf3Q\xc4c~\x81\x90\x1c\xbf\xc0\x1b\x10\xb1\xd8Ҋ\u007f[\xc0\a\xaf\x1d{\xe9\xd8\x17:\xa9\xac\x95\xc5c\x9cU\xb2ه\xf6\x881\tʄyp\xcdL\ueffa*\x13C;C\x88\xf6\xcb\xd8\xf6[2\xc9\xe9\xffVXG\xe3/\xe2`'\x9ed\xbe\x1f\xaf\xaf~\x1f\x05\xefċl\xf5H\x02\x1etd\xd8\xe58\x93\x98\xbd\x1f-N\xa9c&c\xed\xd7<+3t\xacʤb\xc3\xf6䩄\xed$\aƭ\x18VY`\x06\x81A\xcb4I\xee\x01\xf7\xcb\x10\xe25\x13\x14\x9f)\x04\xf7}\x0e`Z7\"\x1b\x8ac \x8fIh\xe4\x04\x15ڬ\xb2\xc7\ue795ð\xafsF\n\x1f\aK\x93\f\xcet\x96\\\x9d\xb3\xd4Q\xbfi\x8e\x16e\xd7Ρ,\xe1Ai\xc12\xe3\x06\xad\x13ef\xe2\xd5<\xd38!\xac\xc0\xcb3<\x88-\xe8L\xf1\x12E\x112\xbd\xbe\x80\xf1]\xc7\\\x85p\xbc<8\n\x91*t\xca[\xc7\x10\x97\xf9Rr\xb2\x86J\xabɐV|1ed\xa6\xf3\x98&G\x9d\xd1!\xd2y}\xed\x1b\xdeϨ\xb0C#?\xf24\xf8S\x97\xda\xfbTL\xbc\xb4\xc6.\x15\xe5\xe9㧕\xd3⽜\xef\xf0\xed,ã\xba\x8b\x96\xacw\xd0\xf6\x8fg\xe4\x8ad\x18\x90\v;}\x04#j\xc8}\x12M9\xfe\x96\x89\x069\xa4\xb7\x9d\xe9\x9e\f\xd5!\x95\rn\xc9\xdd\a\xd3K\xa5i\x84\xd7'\xaa5\x82\xf5}\xa2\v{\x82fg\x91\xfb\x9eF\x86\t\xf3\xe4u\xabL\xcb\\\xe8k.\xb3De\xd74l\xd3\xe0\x1a\x9c\xe9\xe6\xd3',\xb1EkYu\xce\x14\u007f\x0e\xabB\xc5\x1e\xb7\x00ۨ\xce\xf5%\xfb\xc8=^بS\xcf\xeb\x1ad\x8b\xe1\xb1:3*VlLڛ\xc6\xef\x19:\x82Ã\xa0G\xb5\xc1|\xd0\u007f\x89O\x00\xf0\x0fZ\xe7\x10Қ\x9c\x81\xf5\xde뤅\xc1\t\xa7|\x83\x8f\x99\xd1\xd9C\xdcp\xf22\x99Lf\xeeGo\rϺ\u007f<\xe8\x1c\v\xe22\xa8U\x93\x8cY9ր\xec\xda\r\x1a\xe2\xc3f\xefЎ\xddy\xae?\xe3\xeb\xba\x03\x1b\a\xfb\x93\xfc\x02\xa5X\xaa\x96L\xfa>*Y\x97S\xc0\x85\xd5\r\xdbg\b\xa7\x8b\xf8܍\x8c\x8b\\\xc0A\x9f\x93Qk4~\xea\xb9}%\x8f\xe9J\xc9#\x95F\xb2g!\xdd_\xffr\"\xd3\x13\xd2a5\t\x0eq\x9e\xd8\xf9\x03\x9d\xf2uN8\x91\xc4Xɴ\xad\x95\xbb\xbe:\xa3\x05w\xfd\xc2d\r\xb3\xe79\xec\xa9EUȉ\xaa\xf7-\xcf2\xd5\xf1\x13\xf09\xa8\xa3\xc5g\xa2P||\xceŠ;\xd4̐\xa5\xfb7\x81\xcb\xe9\xa3\xd5k\xb0\xc27:)\xf3\f\xa9hhCX\nN\x94Z)\x83\x19\x97\t\xf3\xb02\n\"c\xf8\xbfg\xfc\xc8\xea\xc9l\xd0#\xe7\x03ڱY>\x1c\xe96\xfdC\xd0\x1a~\xfdmqHlXI\xc5\x13\xf2\x9b\xe9\x1fYĔ3\xfdՄ\xffY*\x19*\t\xbb\x86O\x9f\x17\xe9\xd9\xf2>\xfd1\x04\r\xfe/\x00\x00\xff\xff\xb0\xddǼ\x99\"\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4YKs\x1b\xb9\x11\xbe\xf3Wti\x0f\xcaV\x99\xc3]'\x95\xa4x\xb3\xa5lJɮ\xac2e]\\>\x80\x83\xe6\f\x963\x00\x02`H3[\xfb\xdfS\x8d\a9/\x92\xa2*Z\xcf\xc5\x16\xd0h|\xf8\xd0/4'\xd3\xe9t´xBc\x85\x92s`Z\xe0W\x87\x92\xfe\xb2\xd9\xfa\xef6\x13j\xb6\xf9q\xb2\x16\x92\xcfᦱN\xd5\x1fѪ\xc6\xe4x\x8b+!\x85\x13JNjt\x8c3\xc7\xe6\x13\x00&\xa5r\x8c\x86-\xfd\t\x90+錪*4\xd3\x02e\xb6n\x96\xb8lD\xc5\xd1x\xe5i\xeb\xcd\x0f\xd9߲\x1f&\x00\xb9A\xbf\xfcQ\xd4h\x1d\xab\xf5\x1cdSU\x13\x00\xc9j\x9c\x83V|\xa3\xaa\xa6F\x83\xd6)\x836\xdb`\x85FeBM\xacƜv-\x8cj\xf4\x1c\x0e\x13aqD\x14N\xf3\xa0\xf8\x93\xd7\xf31\xe8\xf1S\x95\xb0\xeeߣ\xd3?\v뼈\xae\x1aê\x11\x1c~\xd6\nY4\x153\xc3\xf9\t\x80͕\xc69\xdc\x13\x14\xcdr\xe4\x13\x80H\x80\x876\x05ƹ\xa7\x94U\x0fFH\x87\xe6\x86T$*\xa7\xc0\xd1\xe6Fh\xe7)\xdb\xeb\x01\xb5\x02W\"m\xe9\xe9fB\nY\xf8\xa1\x00\x01\x9c\x82%BD½2\x80_\xad\x92\x0f̕sȈ\xb8L+\x9eɤ3\xca\x04\xce\xef{\xa3nG\xe7\xb0\xce\bY\x1cC\xf6\u007f\x06\xd5\xc1\xf3\xa0\xf83\x91<\x96\xe8e\x12\x9aFW\x8aq4\xb4y\xc9$\xaf\x10\xc8r\xc1\x19&\xed\n\xcd\x11\x14i\xd9\xe3Nw\x91|J\xfaZ3\x97\xb0s\t\x15A\xb6\xb3\xfdS{\xe8ܾ\x0f\x8a\xc7\x05\x10\x8d\x1a\xacc\xae\xb1`\x9b\xbc\x04f\xe1\x1e\xb7\xb3;\xf9`Ta\xd0\xda\x11\x18^<\xd3%\xb3]\x1c\v?\xf1\xba8V\xca\xd4\xcc\xcdAH\xf7\u05ff\x1c\xc7\x16\x17eN9V\xbd\xdf9\xb4\x1d\xa4\x8f\xfdဖ\x9c\xad\x88\xd7\xffM\xe0.\tҭ\x92]^\xdf\xf7F\xc7\xc0\xb6\x94\xa6@\x9c\r\x82hG뻢\xab\x8f3\x17\x06\xc2\xf4\xe6\xc7\x10\xca\xf2\x12k6\x8f\x92J\xa3|\xf7p\xf7\xf4\xe7Eg\x18@\x1b\xa5\xd18\x91\xa2k\xf8ZY\xa55\n]f\xafIa\x90\x02N\xe9\x04mp\x8a0\x86\xa3f5\xff\xce\xc4\xfck\xaf;X\aN\x17>\x9f\xebN\xdc\x00%;\x10\x16X\\\x1aNq :\x85\xec\x8f\xffX\xdc\xcf\xfe9\xc6\xfc\xfe\x14\xc0\xf2\x1c\xad\xf5\xf9\x1ak\x94\xee\xcd>gs\xb4\xc2 \xa7\xc2\x05\xb3\x9aI\xb1B벸\a\x1a\xfb\xf9\xed\x97q\xf6\x00~R\x06\xf0+\xabu\x85o@\x04\xc6\xf7\xe1/ٌ\xb0\x81\x8e\xbdF\xd8\nW\x8a~\xd2\xda3@\xd6\x15\x8f\xbd\xf5\xc7ul\x8d\xa0\xe2q\x1b\x84J\xacq\x0eW\xbe\x12<\xc0\xfc\x8d\x1c\xeb\xf7\xab#Z\xff\x14\x1c芄\xae\x02\xb8}\xbek{\xe4\x01\xa4+\x99\x03gDQ\xe0\xa1\x10\xed\u007f>xSH\xfc\x1e\x94!\x06\xa4j\xa9\xf0\x8a\xe9\xf6B\x00\xfd\xf9헣\x88\xbb|\x81\x90\x1c\xbf\xc2[\x102p\xa3\x15\xff>\x83Go\x1d;\xe9\xd8W\xda)/\x95\xc5c\xcc*Y\xedB\xb5\xbfA\xb0\xaaF\xd8bUMC\xbd\xc1a\xcbv\xc4B\xba8\xb27\x06\x9a\x19w\xd2ZS\x95\xf1\xf8\xe1\xf6\xc3< #\x83*|\xbc\xa3\xec\xb4\x12T5P\xb9\x10r\x9e\xb7\xc6A\xd2L\x9fm\x82\xf98\x05y\xc9d\x81\xe1\xbc\b\xab\x86\xb2Pv\xfd\x12?\x1e\xa6\xfe\xf4\x8d\x94\x00\xfd\xc0\xf1͒\xe83\x0f\xe7+\xd5g\x1c\xae\xfd\xd6:y\xb8u\xb3D#ѡ?\x1fW\xb9\xa5\xa3娝\x9d\xa9\r\x9a\x8d\xc0\xedl\xab\xccZ\xc8bJ\xa69\r6`g\xfe\xc9<\xfb\xce\xff\xf3\xe2\xb3\xf8\xd7\xf5s\x0f\xd4y\xf4\xbf\xe6\xa9h\x1f;{ѡR\xad\xf8\xfc2q5\xacTN0\x11\f\xe0\f\a\xb1\x994\xf22\x8a\xf6\x13*E?B\xaf\x11oE\xe3!\xf6R\xbb\xa2\x874\x95\xbd]\x84\xd3\xf1\xf7^OF+>\xe9\x93\xd6v\xc9\xde\xe4\xc1\xa1\xfa\x13][\xed\xcdv\x9a\x9c\xed\xd3\f\x9fʾ\x83v\xc9c9t\xed\"\xef!f\xbb\xd4ˣ\aˋ\x9f˹\xa2\xc7@\xf7W\x8b\xd36p3\\\xe1{S\x86G\x9f\x105\xfa7hh8n\x99M\x9b\x8c\xdd7\xb4\xf4\x85\xa5>O\x92:\xe4\xbeT\xa7\x97Ċ\x89\n9\xec\u007f7\xf1\xcdq\xeb\x9b4\xd7c\x95iR\xd4X\xe4>n\x8c\x80\x1e\xaeK}O\xce\x1cNI\xc5@B6UŖ\x15\xce\xc1\x99f8}½j\xb4\x96\x15\xe7\xfc\xeb\x97 \x15^\xf1q\t\xb0\xa5j\xdc\xfe\x19\x1f\x1d-Rqm\xa3\x15\\\xd6J(\x99=\a\xe5\x81d\xc6,n\xef\xf2\xa7M\x0eN\x84\xb2{\u070e\x8c\x0e\xfa\xd0\xedɛdB#s?y븈\x80\xb8\xd19\x0e\xa2\x18\x94\xaaJ֭\x1c%\xa5\xa6^\xa2!\"|\xf3;1\x92\x02\xc7X_Ŀ\xa7\x0eL\x1e4\xa4X\x18T\xc5\x17bΤo\x13\x92\xfd:\x05\\X]\xb1݈\xdet\x12_2\x91\xf9\x92\x1f\x1d,&y!\xb9\xbf\x9f\xbb\xb4\x9f\xb3o\xee\x8f\x17tc?\x15\x8c\xddB\xbb\xefߛ\xdf\xff\xaa\xf1:;\x9c(\xe2\xacc\xc6=7\xec-:\xc2\xe7\"\x9eW=\x1e\xefڡk\x18\xa8\xba\xdb\xfc\x911j\x94\xa8\xc1\xa0G\xce[\xbac/\xb4=\xd2,\xf7\x9d\xfe9\xfc\xf6\xfb\xe4\x90\xeeXNU;\xf2\xfb\xfeOڱVI\xbfP\xfb?s%\xc3O\xcav\x0e\x9f\xbfL 6M\x9f\xd2\xcf\xce4\xf8\xbf\x00\x00\x00\xff\xffe\xe5\xd5&\b \x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xdc<\xcbr۸\x96{\u007f\xc5)\xcf\"3U\x96ܩY̔w\x19wR\xed\xea\xee\xc4e\xa7ҋ\xa9\xbb\x80\xc8#\tm\x10`\xe3!G\xf7\xd6\xfd\xf7[x\xf1!\x82$$[\xe9\xf4\xe5N\x14p\x80\xf3\xc0y\x13\x17\x8b\xc5\xe2\x82\xd4\xf4\vJE\x05\xbf\x01RS\xfc\xaa\x91\xdb_j\xf9\xf4\xbfjI\xc5\xf5\xee\xed\xc5\x13\xe5\xe5\r\xdc\x1a\xa5E\xf5\x80J\x18Y\xe0\x8f\xb8\xa6\x9cj*\xf8E\x85\x9a\x94D\x93\x9b\v\x00¹\xd0ľV\xf6'@!\xb8\x96\x821\x94\x8b\r\xf2\xe5\x93Y\xe1\xcaPV\xa2t\xc0\xe3һ\x1f\x96\xff\xb3\xfc\xe1\x02\xa0\x90\xe8\xa6\u007f\xa6\x15*M\xaa\xfa\x06\xb8a\xec\x02\x80\x93\no@\xa2\xd2B\xa2Z\ue421\x14K*.T\x8d\x85]l#\x85\xa9o\xa0\xfd\xc3\xcf\t\x1b\xf1H<\xf8\xe9\xee\r\xa3J\xff\xdc}\xfb\vU\xda\xfdS3#\tk\x17s/\x15\xe5\x1bÈl^_\x00\xa8B\xd4x\x03\x1f\xed25)\xb0\xbc\x00\b8\xb9e\x17a\u05fb\xb7\x1eD\xb1Ŋ\xf8\xfd\x00\x88\x1a\xf9\xbb\xfb\xbb/\xff\xfd\xd8{\rP\xa2*$\xad\xb5\xa3L\xd8\x1bP\x05\x04\xbe8\xdc\xec\x06\x1c\x13@o\x89\x06\x89\xb5D\x85\\+\xd0[\x04R\u05cc\x16\x8e\x88\rD\x00\xb1nf)XKQ\xb5\xd0V\xa4x25h\x01\x044\x91\x1b\xd4\xf0\xb3Y\xa1\xe4\xa8QA\xc1\x8c\xd2(\x97\r\xacZ\x8a\x1a\xa5\xa6\x91\xb0\xfe\xe9\xc8Q\xe7\xed\x01.o,\xba~\x14\x94V\x80\xd0o9\x90\f\xcb@!\xbb[\xbd\xa5\xaaE\xed\x10\x9d\x80\x12\xe1 V\xbfc\xa1\x97\xf0\x88҂\x01\xb5\x15\x86\x95V\xeev(-q\n\xb1\xe1\xf4\xef\rle\x11\xb5\x8b2\xa21\xf0\xbb}(\xd7(9a\xb0#\xcc\xe0\x15\x10^BE\xf6 Ѯ\x02\x86w\xe0\xb9!j\t\xbf:\xf6\U00035e01\xadֵ\xba\xb9\xbe\xdeP\x1d\xcfO!\xaa\xcap\xaa\xf7\xd7\xee(Е\xd1B\xaa\xeb\x12wȮ\x15\xdd,\x88,\xb6Tc\xa1\x8d\xc4kRӅ\xdb:wghY\x95\xffѰ\xedMo\xafzo%OiI\xf9\xa6\xf3\x87\x13\xf3\t\x0eX\x81\xf7\xb2\xe4\xa7z,ZB\xdbW\x96:\x0f\xef\x1f?w匪C\xea;\xbaw\x84\xafe\x81%\x18\xe5k\x94\x9e\x89N\xda,L\xe4e-(\xd7\xeeG\xc1(\xf2C\xf2+\xb3\xaa\xa8\xb6|\xffà\xb2\x02-\x96p\xeb\x94\n\xac\x10L]\x12\x8d\xe5\x12\xee8ܒ\n\xd9-Qxv\x06XJ\xab\x85%l\x1e\v\xba\xfa\xf0p\xb0\xa7Z珨\xbcF\xf8\x15N\xffc\x8dE\xef\xc4\xd8it\x1d\x8e9\xac\x85\xec)\a;e\xd9\x03\x9a>\xb4\xf6\xf1\xa7\xdfj\xb0\xc3\u007f\x0e\xb6\xf2\u007f\xcd@+?v\x13\x86\xd3?\f:\x15\xe7O,\x0eT\xca\x00$\xc4\xfd9\xb1X\x0e\xfe\x1f\xa1\xa9}\xf0k\xc1L\x89e\xa3m\a\xb8\x1c\xec\xf8\xfd`\x823G\x84r+\xffV\xfd\xdbm\xf3\xf6_\xabN\x13;&\x12\xc1J \xe5\x1e\x1eP\xee\x90MR\xda>Tc\x95\xd8\xdc$v\xe0\xec\x1cY1\xbc\x01-\r\x8eP\x86HI\xf6#\x84\x89\xb69\x97.\xcd\xf8\xa0\x10\x18-\xb0k(q\f\x12\xfa\x86y\x06.\xb8\xf8\x95J\xac|\\\xfc\xd9Q\xb3}\xe3\x02\x8aw\x1f\u007f\xc4r\x8a<\x90'y\x03D\xde\x1dl\xb6\xbbtp\xf4s\xd1\b\xaeO\x134\xf9\x8c\xc7\x15\x10x½\xf7X\b\a\xcb\x1c\xa2\x9d\xbf\x9b\f\x9f\x86\xc4q\xa9\x17\xef\x1e\xe3ށ\t\xb9\x94\xd9ٹ\xa2\xe0\x9f'L\xf8\xfb\xa9\xa7G@\xbb\xa7\x10\xe1zJ\xda\x17\x8e\x10.\xf2\xce'\x1e\xb8\xbcX\xd4E\xf3\xc8A\xbe\"\x89O\xa4\xfd\th6l\xeb\xe4\x0f\x1dc\xdf(\xcf\"{\n\xb6\xb4\xceDԥ\x0f\x15\xba\xd3\x123c_\b\xa3e\xb3\x90\x97\xfb;>\xee\r\xf7\x9f\x8fB\xdf\xf1+\x1f\x92)'%?\nT\x1f\x85vo\xceBN\xbf\xf1\x13\x88\xe9'\xba\xe3Žڶt\xe8\xa6\xd82\x84\xdb?w>\x93Ұ\x87*\xb8\xe36p\t\xf4p\tS\xbfܴ}\xe8?\x95Q.\x87\xc6\x05_8S\xb9L\xad䉝\tR\xc8\x1eG\x86[k\x16\xf5\vf\x82\xfdl-\x89\x9f\xefS\xc0\x8c\x14X\xc6h\xd3%.\x89\xc6\r-\xa0B\xb9\x992\x1cݧ\xb6\xfa=o\v\x99Z\xd7?GJX\x9ei\x8fOP\xdd\xe5\xfcf\x16\xf6\xe4f\x8c\x8a̞\x1d:\x92\xaf\x1c\x1f:\x8f\x913\xb1\xce\xff\x98\xa5.)KW\\\"\xec\xfe\b\x8d\u007f\x04/\x86\xb6\xdfo\xcc[Ȋ\xd4\xf6\xfc\xfeÚ9'\xd0\xff\x84\x9aP\x99q\x86߹:\x11\xc3\xdeܐ\x19\xeb.cW\xa0\n,\u007fw\x84\r3\xe1\t\xe4\x84\xd5-ȼ!\x17\xeb\x81\xc7r\x05\xcf[\xa1\xbcM]Sd\xa9\x94M\xff\xa1\n.\x9fp\u007fy5\xd0\x03\x97w\xfc\xd2\x1b\xf8\xa3\xd5M\xe3-\b\xce\xf6p\xe9\xe6^\xbe\xc4\tʔĬa<\x99\xe7n\x9f\x9eXts\xddm\x92;\xb8\xb9S\xbbΒ\xc3Z(\xfdS:a7\xb2\x9f\xfb8\xa3\xef\x9b&\xf2^\xb3>{\xc8a5J\xd5zrk\x8d2$\U0007c88d\x11\xc0\vc\xa3\xb9$]\x93\xa0#Mf\xd5\x12xF*|\xcd#g\x8b\xc7x\x8d\x96.G\xfa\xdb\xef\xbfvr\x8c\xf6\x84\xda\xdf]D^۫-DU\x91\xc3*_\xd6Vo\xfd\xcc(\xd3\x01\x90\xe7\xbe\xdc\x18w.\xf3ݽ(C\xae\xbe\xf7L\xf5\x96r \xf1\xf8\xa3\f\x02E\xa0\x16\xf3\x9a\xc8?[\xa2`\x85ț\xdc\xf8\xf7`\xaf+\xca\xef\xdc\x02\xf0\xf6\xd5\xed;\xb4\xe4:\x89\x9d\x91\xd4\rC\x9b\x17\xce\xe2\xe4\xbaF\xa2\x84\xe7-J\xecI\xc50\xe1m=\xc6L\x90\\\xe8n^\xc1\u00adE\xf9F\xc1\x9aJ\xa5\xbb\x1b\xcd\x158\xa3r\xc5\xe1H\x0e[\xec>\xd3\n\x85\xd1'\xf0\xe0};\xbbW\xa0\xad\xc8WZ\x99\nH%L\x86q\xf7\x8f\xb5/\xb4j\xaa\xa8\x81\x03τꦞ\xe42,ZX.\xd5\fu.\x8bW\xb8\xb6\xea\xa8\x10\\\xd1\x12e\xac\xf2{\xceRa\x0f\xee\x9aPfR\xe5\x9b\xd4sl\x98\xca\xdfKyR\x94\xfa\xc9\xcf\xecd\r\xb7\xe2\xb9O\xa0l\x12l\xc9\x0e\x81\xae\x81j@^X\xbe\xa0\xf4*\xdb-\x11\x88\xe1H\x93-\x96y\n\xde>\xc8M\x95G\x80\x85;ٔO&ź\xc3?\x10\xca\xce\xc16+y\xa7\x1f\x8d\xdf\xda\xd9\xdf\xe4h4J%߄\xad\x10\x1e\x90\x94\xfbx>\x88\xd66Tu2 @\x1a\xdeՈg8\x19\xc7\xc4wa\x17\xaf\x19\xb8QN3\x18{\x90ϧ\xba\xeb\xedX\x10g\xf5v\xec\x02\x8d\xa1;%5s\xd7\x03`Met\x9c\xdd\xde\x1b\xa99\xc2\xf3Y\xa1\rP\xb1\xf4I/k>\x83\x1f\xed{\x97F\xca\xe0I\xec\x8ew]\xb28\u06dd\x90\x9f%\xfa\xbah\xdb\x15\x16.)(w\xb80\xfc\x89\x8bg\xbep1\xa5\x9a\xcd\xd67\x8b\x9f\xac8\xbe\xa5\xd2\xe8\x8bW\xbe\bD\xfb{\x06\xa5\x90\xcd\xe6\xa3\x02\xe3))\x98SC\xbe\x8du\xe4\xcf\xd9]L\xad?19\xd4\x1co}\xffino\xd3]zV\xc7\u007fxޢޢ\x8c\x8d\xad\v\xd7ÛR\xabmi\xb2u\x85\x9bf'+?ћ\xf2Mx\a\xedOi_\x99\x1bƮ\xac`\x13ôoE\x95&!DY=@+!\x18\x92ö\u061c\"\xfa\\\xe9\xbc\xdf\x0f֔\xaecC\x98\x88\x8b$0\xf4\xbc\xf4]\x9fݺl\xbf\x06\xee\xb2?q\xa7\u007fz\xabXFy{\xa6\xa8=\xdd@7E\xaf\xa1\xd8t)\xd6\xca`\x18\x17:+\xbf+\xf2\xcd\x14\xa2\xc7\xcb\xcf!ي\x9a\xec\xde.\xfb\xffh\x11\x8a\xd1.\xb3\x90@\xe5y\xdb\xe4\t\x9c\xe5\xe5%\xdd\xd1\xd2\x10֓\xc0\x0e\xcdZ҂\x90\xc0)Kա,\xcd\xe3\xfc\x1e\x8d\xe1S\xed\xf3\xd1G\x9f\xd5iw'\xaff}r\xa5\xba_\x89\x1e\xd1\xe0Ǧf\xf3[\xf2\xf2k\xd1\xd3\xc5\xe3c*Ї\xf5\xe5Q\xa0\xf3u\xe7\x1cOu\xa6\xc6|Be9\xb3\xab\xe8\xc5\t\xe8\x9c\xda\xf1I\x15\xe3\xd9ƛ\xcc:q\xbf\x02<\r\xf2\x88\xeap\x16q\xe6+\xc1G\xd7\u007fC\xbdu\x12\x8f\xec\xaao\xa2\x9e;\tx\xb4\xd6;Uŝ&y\xa2\u009b_\xbb\x9d\x04\xed\xea\xba\xf3\x15\xdb\xd7\xeb\xcbz\r\x17y\\\xd5\xccV]_\xe4Bg\xd4U\x8f\xa9\xa6\xceR\xec\xc4\xcaiS\x19\x1dY\xf7\xd8zi\xbf\x1e:\x024\xa7J:R\x05\x1d\x818Y\x1bͭ}\x8e\xc0\x9e1\xbb\x93R2\xf1g\xe3u\xffJ\xea\x9a\xf2͐\xf3\xb9\xf21)\x1b\x83\xd2iw͞pt\x9d\xe3^X\x91Z\xd2\u007f\x90\x98\bAb҉r-\x96\xf0\x8e\xef\ap]3t\xd2\xe5\xee\u007f\xb1b\xb7\xf5L\x19\xeb~\x95\xe1\xc0vA\x85\x0f\x9cT:\x10\xb6\x03\xc7>fJ2EȞ\xbf;\x17q|:\x18\xdeMcM\xfb\xcf)י\xea\xed\x89\xfese\x98\xa6u\xf2\x10\xd7R\xec\xa8K\x8amq\xdf\xd0\xf3wᾇX\xed\x1d\xa4O\x0f\xcd\xf9Z\x1e\x84\x02$u*\x9e\x911 j\x88~\xe1\xbf\t,\xc4\xc2}\xe6c9\x19\xe5!|;x\xe5\xce`*@\xe5\xf1k\xb5ʂq\xdf\x15\xaaD\x02`ԺL{\xb8\xde\x19w\xef\xfe0(\xf7 v\xae\n\x1a\\\x9e\x99\x86c\xaf)\x94am\x87GP\x80\xfeK\xd4\x03Ͽ\xd5\x18\xf0\x8e{\x1b\x9c\x04{\xb0G\a\xc7*\xad6ڱ\xfa\xd9\x062#C\x93P\xb9hf\xa7\xe5a\xd2\xd4\xe4v\xeb\x9e7\xf69>\xfa\x99\xf5;\xce\x12\x01\x9d\x1e\x03M\x80\xcc\xed\xbe\xcd\xcb\xd8\xcfv۞+\x16\x9a\x8b\x86\xb2\xdd\xc0\xbcn\xdast\xd1\x1e\xd1={DTt\\\\\x94M\xa6\x9c.ٳDGg\x8c\x8f\xce\x11!\x9d\x16#̀<\xe8~\xcd\xe9k\xcd*2e\x97(r\x8aJ\xf3u\xcd\xe9~Ռ>Ռ\xe2\xc7\xdcN3\xfaQ\x8f\xebC͠ᙢ\xa73\xc5O爠\xce\x1bC\xcdFQ\xb3\x923\xf9\xf7\xc99\xf2XM\xfd(J\xbc\x17R\xcf9\xfc\xf7\x87\xe3\x13\x15\xacN\x10$X\t<\x0eM \xe5|\xf9\xe0ǟ\x86T\xba\xd8\x14ֿ\xff2\x87\xcfC3p\x1a\x11\xeb\x92\xc6\xf8,\x81\x87\x9d\xefpQ\x9c\xd4j\x9b\b\xef^\x8ẹ&\xdad\xe2\xe3\xc7\xf6P\xa2ŶS\xb6y\xc6X=\x94\x9d\xab\x87\x0e\xf6d\x1d\x1e\x0fȝ'g\v9eW\x1d\x0f\xfb\xdbT#2\xbfl>\xf9\x9bfO\x9e\x91s\xe9BF\x1b\xd5EYh\xe9rB\x1dbV\x17g|~8m@2?\x8a=\xf9s\xd8yb%\b5\xf6%l\xce\u05ee\u007f*='Ԯ*\xb6X\x1a\x86\x19\x97\xd4\xcdB\xa6o`\x92r>U\xe9\xfau\x83?\xeb\x9al\x1d{\x19\v]\xb6\x15*E6\xf1Z\xa1g\x94\b\x1b\xe4\x96\xc4Sw̴\x8d\xca\xe1\x047\xfd\x12\x96Z\xa4І\x84\x05\xbc\xa5l\x92\xb8\xa9\x04\xa0\xbf\xb9\xcc\x0e!\x9b\xd1sC\xb9\xc6\xcd }\x1a\x9a\xa4\x1f\x90\xa8Û\xee\x06\x84\xf8\xd0\x1d\x1b\x82_O\x03\xffU5q<\xf5\x17\xa3i*q\xcaC\x10n壮˪\xb7Dͩ\xcb{;\xa6\xf9z\xa0s(\x1bM\xf90\xb2\xa7t7\xf3\x02>\xe2s\xe2\xed\a'\xf4.\xa1\x91>J\v\xb8\xe3\xf7Rll\x8c\x91\xf8\xf37B5\xe5\x9b\x0fB\xde3\xb3\xa1\xfcS<\x93\xc7\r\xbe'RS\xc2\xd8\xde\xef'1\xf76\x1e\xe6\xc4\u007f\xf3\xb3G\xfe\x98bR\xc0y6\x1a\xf0\xc3\xda\xe0\x88r\u007f\xd0]\xef\xfeJ\x18\xdd=\x15oT{`ҙY\am\t\x1f\x85Ƙt\xa3}\xa0T\xc1\n\x95^\xe0z-\xa4\xf6\xc1\xd8b\x01t\x1d\x14u*\xc8 \x949_\xc3\xdf\xd3g\x1d\x90\xa6\xf0\xdbX>!\x81\xf0=Hw*\x9c\x93R\x91\xbdo\xad#Ea\xac\x1e\xb8V\x9a\xa4\fڋ\\[\xe7\xdc\x04i\x1e\xc9K\xf4=\xb5\xee\xf8\xe6+@S\xadP\xba\xdea\xfb\xb7'\x9d\xfb\xac\xc0\xab\xa0d\xc1\x01\xdc\xc7\a\x9d\xaf\x9a@\xd9㜎\x8f\xa7\x94\x8f\xfb_h\xc2\xee\xc6\x1d\xb5~#m38\"\xe0\xa6\x0f\xd1\xe8]H6\xde&DU\x9cjyVl\t\xdfX\xf1\x91\xc2l\xb6Q\x04\xc74\xf5X>ĸ\xfb\xd0jwRUL^k#y'\xf7\x12\xd2\xd9e\xbb\xdd)\xa0\xd3$\x9c\xf23{\xa6u\xce\xd3\xec\r~\x99\v\xe1\x16\xb6\x0e\xc4\xf7k\xfaw\x8d\xee~\x9f\xe3\x04|9\x18~\xd0 i݁\x16b0\xdc\t\xe2\xfc']\xc7\xfblW\f\xffk0\xe2\x1b7:>\x13\xc9)\xdf\xcc!\xff[\x18\x96\xf0\x81\x02\x84\x84\x17\x94@\xa2\xf1\x8b\x8e\xf2\x82\xe2&G\xaell<\xa3\x17\xf8A\xc934x\xe9\x04\xb9\xec\x109\xac\x14\u07b4\xf1\x03)\n\xacuh@\xee\xde\xd6|y\xe9~\xc4\xeb\x98\xdd\xcfBp\xaf\x16\xd4\r\xfc\xff\xdf.\"B_\xe2\xad\xcb\xf6\xe5\xbf\x02\x00\x00\xff\xff鐱=\xdaZ\x00\x00"), diff --git a/pkg/apis/velero/v1/download_request_types.go b/pkg/apis/velero/v1/download_request_types.go index acb48c4d34..a5ce777939 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;RestoreLog;RestoreResults;RestoreResourceList;RestoreItemOperations;CSIBackupVolumeSnapshots;CSIBackupVolumeSnapshotContents +// +kubebuilder:validation:Enum=BackupLog;BackupContents;BackupVolumeSnapshots;BackupItemOperations;BackupResourceList;BackupResults;RestoreLog;RestoreResults;RestoreResourceList;RestoreItemOperations;CSIBackupVolumeSnapshots;CSIBackupVolumeSnapshotContents type DownloadTargetKind string const ( @@ -34,6 +34,7 @@ const ( DownloadTargetKindBackupVolumeSnapshots DownloadTargetKind = "BackupVolumeSnapshots" DownloadTargetKindBackupItemOperations DownloadTargetKind = "BackupItemOperations" DownloadTargetKindBackupResourceList DownloadTargetKind = "BackupResourceList" + DownloadTargetKindBackupResults DownloadTargetKind = "BackupResults" DownloadTargetKindRestoreLog DownloadTargetKind = "RestoreLog" DownloadTargetKindRestoreResults DownloadTargetKind = "RestoreResults" DownloadTargetKindRestoreResourceList DownloadTargetKind = "RestoreResourceList" diff --git a/pkg/cmd/util/output/backup_describer.go b/pkg/cmd/util/output/backup_describer.go index 8c73e6cf7f..d3decfeced 100644 --- a/pkg/cmd/util/output/backup_describer.go +++ b/pkg/cmd/util/output/backup_describer.go @@ -36,6 +36,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/features" clientset "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned" "github.com/vmware-tanzu/velero/pkg/itemoperation" + "github.com/vmware-tanzu/velero/pkg/util/results" "github.com/vmware-tanzu/velero/pkg/volume" ) @@ -90,8 +91,7 @@ func DescribeBackup( } d.Println() - d.Printf("Errors:\t%d\n", status.Errors) - d.Printf("Warnings:\t%d\n", status.Warnings) + DescribeBackupResults(ctx, kbClient, d, backup, insecureSkipTLSVerify, caCertFile) d.Println() DescribeBackupSpec(d, backup.Spec) @@ -632,3 +632,39 @@ func DescribeVSC(d *Describer, details bool, vsc snapshotv1api.VolumeSnapshotCon d.Printf("\tReady to use: %t\n", *vsc.Status.ReadyToUse) } } + +// DescribeBackupResults describes errors and warnings in human-readable format. +func DescribeBackupResults(ctx context.Context, kbClient kbclient.Client, d *Describer, backup *velerov1api.Backup, insecureSkipTLSVerify bool, caCertPath string) { + if backup.Status.Warnings == 0 && backup.Status.Errors == 0 { + return + } + + var buf bytes.Buffer + var resultMap map[string]results.Result + + // If err 'ErrNotFound' occurs, it means the backup bundle in the bucket has already been there before the backup-result file is introduced. + // We only display the count of errors and warnings in this case. + err := downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupResults, &buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath) + if err == downloadrequest.ErrNotFound { + d.Printf("Errors:\t%d\n", backup.Status.Errors) + d.Printf("Warnings:\t%d\n", backup.Status.Warnings) + return + } else if err != nil { + d.Printf("Warnings:\t\n\nErrors:\t\n", err, err) + return + } + + if err := json.NewDecoder(&buf).Decode(&resultMap); err != nil { + d.Printf("Warnings:\t\n\nErrors:\t\n", err, err) + return + } + + if backup.Status.Warnings > 0 { + d.Println() + describeResult(d, "Warnings", resultMap["warnings"]) + } + if backup.Status.Errors > 0 { + d.Println() + describeResult(d, "Errors", resultMap["errors"]) + } +} diff --git a/pkg/cmd/util/output/backup_structured_describer.go b/pkg/cmd/util/output/backup_structured_describer.go index 6797c80a60..a20f8d2292 100644 --- a/pkg/cmd/util/output/backup_structured_describer.go +++ b/pkg/cmd/util/output/backup_structured_describer.go @@ -33,6 +33,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/cmd/util/downloadrequest" "github.com/vmware-tanzu/velero/pkg/features" clientset "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned" + "github.com/vmware-tanzu/velero/pkg/util/results" "github.com/vmware-tanzu/velero/pkg/volume" ) @@ -60,8 +61,7 @@ func DescribeBackupInSF( d.Describe("validationErrors", status.ValidationErrors) } - d.Describe("errors", status.Errors) - d.Describe("warnings", status.Warnings) + DescribeBackupResultsInSF(ctx, kbClient, d, backup, insecureSkipTLSVerify, caCertFile) DescribeBackupSpecInSF(d, backup.Spec) @@ -266,7 +266,7 @@ func DescribeBackupStatusInSF(ctx context.Context, kbClient kbclient.Client, d * // In consideration of decoding structured output conveniently, the three separate fields were created here // the field of "veleroNativeSnapshots" displays the brief snapshots info - // the field of "veleroNativeSnapshotsError" displays the error message if it fails to get snapshot info + // the field of "errorGettingSnapshots" displays the error message if it fails to get snapshot info // the field of "veleroNativeSnapshotsDetail" displays the detailed snapshots info if status.VolumeSnapshotsAttempted > 0 { if !details { @@ -276,13 +276,13 @@ func DescribeBackupStatusInSF(ctx context.Context, kbClient kbclient.Client, d * buf := new(bytes.Buffer) if err := downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupVolumeSnapshots, buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath); err != nil { - backupStatusInfo["veleroNativeSnapshotsError"] = fmt.Sprintf("", err) + backupStatusInfo["errorGettingSnapshots"] = fmt.Sprintf("", err) return } var snapshots []*volume.Snapshot if err := json.NewDecoder(buf).Decode(&snapshots); err != nil { - backupStatusInfo["veleroNativeSnapshotsError"] = fmt.Sprintf("", err) + backupStatusInfo["errorGettingSnapshots"] = fmt.Sprintf("", err) return } @@ -298,7 +298,7 @@ func DescribeBackupStatusInSF(ctx context.Context, kbClient kbclient.Client, d * func describeBackupResourceListInSF(ctx context.Context, kbClient kbclient.Client, backupStatusInfo map[string]interface{}, backup *velerov1api.Backup, insecureSkipTLSVerify bool, caCertPath string) { // In consideration of decoding structured output conveniently, the two separate fields were created here(in func describeBackupResourceList, there is only one field describing either error message or resource list) - // the field of 'resourceListError' gives specific error message when it fails to get resources list + // the field of 'errorGettingResourceList' gives specific error message when it fails to get resources list // the field of 'resourceList' lists the rearranged resources buf := new(bytes.Buffer) if err := downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupResourceList, buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath); err != nil { @@ -308,16 +308,16 @@ func describeBackupResourceListInSF(ctx context.Context, kbClient kbclient.Clien // - the backup hasn't completed yet; or // - there was an error uploading the file; or // - the file was manually deleted after upload - backupStatusInfo["resourceListError"] = "" + backupStatusInfo["errorGettingResourceList"] = "" } else { - backupStatusInfo["resourceListError"] = fmt.Sprintf("", err) + backupStatusInfo["errorGettingResourceList"] = fmt.Sprintf("", err) } return } var resourceList map[string][]string if err := json.NewDecoder(buf).Decode(&resourceList); err != nil { - backupStatusInfo["resourceListError"] = fmt.Sprintf("\n", err) + backupStatusInfo["errorGettingResourceList"] = fmt.Sprintf("\n", err) return } backupStatusInfo["resourceList"] = resourceList @@ -460,3 +460,59 @@ func DescribeVSCInSF(details bool, vsc snapshotv1api.VolumeSnapshotContent, vscD } vscDetails[vsc.Name] = content } + +// DescribeBackupResultsInSF describes errors and warnings in structured format. +func DescribeBackupResultsInSF(ctx context.Context, kbClient kbclient.Client, d *StructuredDescriber, backup *velerov1api.Backup, insecureSkipTLSVerify bool, caCertPath string) { + if backup.Status.Warnings == 0 && backup.Status.Errors == 0 { + return + } + + var buf bytes.Buffer + var resultMap map[string]results.Result + + errors, warnings := make(map[string]interface{}), make(map[string]interface{}) + defer func() { + d.Describe("errors", errors) + d.Describe("warnings", warnings) + }() + + // If 'ErrNotFound' occurs, it means the backup bundle in the bucket has already been there before the backup-result file is introduced. + // We only display the count of errors and warnings in this case. + err := downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupResults, &buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath) + if err == downloadrequest.ErrNotFound { + errors["count"] = backup.Status.Errors + warnings["count"] = backup.Status.Warnings + return + } else if err != nil { + errors["errorGettingErrors"] = fmt.Errorf("", err) + warnings["errorGettingWarnings"] = fmt.Errorf("", err) + return + } + + if err := json.NewDecoder(&buf).Decode(&resultMap); err != nil { + errors["errorGettingErrors"] = fmt.Errorf("", err) + warnings["errorGettingWarnings"] = fmt.Errorf("", err) + return + } + + if backup.Status.Warnings > 0 { + describeResultInSF(warnings, resultMap["warnings"]) + } + if backup.Status.Errors > 0 { + describeResultInSF(errors, resultMap["errors"]) + } +} + +func describeResultInSF(m map[string]interface{}, result results.Result) { + m["velero"], m["cluster"], m["namespace"] = []string{}, []string{}, []string{} + + if len(result.Velero) > 0 { + m["velero"] = result.Velero + } + if len(result.Cluster) > 0 { + m["cluster"] = result.Cluster + } + if len(result.Namespaces) > 0 { + m["namespace"] = result.Namespaces + } +} diff --git a/pkg/cmd/util/output/restore_describer.go b/pkg/cmd/util/output/restore_describer.go index ed3f4d8c41..256b7258aa 100644 --- a/pkg/cmd/util/output/restore_describer.go +++ b/pkg/cmd/util/output/restore_describer.go @@ -186,15 +186,15 @@ func describeRestoreResults(ctx context.Context, kbClient kbclient.Client, d *De if restore.Status.Warnings > 0 { d.Println() - describeRestoreResult(d, "Warnings", resultMap["warnings"]) + describeResult(d, "Warnings", resultMap["warnings"]) } if restore.Status.Errors > 0 { d.Println() - describeRestoreResult(d, "Errors", resultMap["errors"]) + describeResult(d, "Errors", resultMap["errors"]) } } -func describeRestoreResult(d *Describer, name string, result results.Result) { +func describeResult(d *Describer, name string, result results.Result) { d.Printf("%s:\n", name) d.DescribeSlice(1, "Velero", result.Velero) d.DescribeSlice(1, "Cluster", result.Cluster) diff --git a/pkg/persistence/object_store.go b/pkg/persistence/object_store.go index 2e6c8edab2..c6ef5939b5 100644 --- a/pkg/persistence/object_store.go +++ b/pkg/persistence/object_store.go @@ -584,6 +584,8 @@ func (s *objectBackupStore) GetDownloadURL(target velerov1api.DownloadTarget) (s return s.objectStore.CreateSignedURL(s.bucket, s.layout.getCSIVolumeSnapshotKey(target.Name), DownloadURLTTL) case velerov1api.DownloadTargetKindCSIBackupVolumeSnapshotContents: return s.objectStore.CreateSignedURL(s.bucket, s.layout.getCSIVolumeSnapshotContentsKey(target.Name), DownloadURLTTL) + case velerov1api.DownloadTargetKindBackupResults: + return s.objectStore.CreateSignedURL(s.bucket, s.layout.getBackupResultsKey(target.Name), DownloadURLTTL) default: return "", errors.Errorf("unsupported download target kind %q", target.Kind) }