From a0dac73c95247a44f55f8381e6105aeb34451c57 Mon Sep 17 00:00:00 2001 From: allenxu404 Date: Wed, 15 Mar 2023 14:20:47 +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 | 41 +++++++++- .../output/backup_structured_describer.go | 74 ++++++++++++++++--- pkg/cmd/util/output/restore_describer.go | 6 +- pkg/persistence/object_store.go | 2 + 8 files changed, 114 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 000000000..98ea1429c --- /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 4c58a9d68..9602c927b 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 bf7f23796..e878e64c0 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=Ms\xdc:rw\xfd\x8a.\xe5\xe0ݔf\xfc\\9$\xa5\x9b\x9flW\xa6ދ\xad\xb2\xb4\xdeC\x92\x03\x86\xec\x99\xc1\x13\bp\x01p\xe4\xd9T\xfe{\n_\xfc\x04Ip(Ǫ\x19\xf2\xbd\x1b\xe9\xd6\"\xe2\xf3\x01\xf5\x01%\x94\"\xa8\xe0\xc8,w\x94!\xa8\x93\xd2Xx\x8e\aŷ\xf5ԷB\xc1\x98\a\xa1`{\n8\x0f\xe7i\xec-\xd92\xbc\x05-\xab\xe1p\x8e\f[!\x18\x92\xbe\x12\xee\xd3\xe13*M\xb3\x19*\\\xf7\xc9\xe0zE\x88 \xfd\x0fvn\x11:l\x1bY\xd3\xe4\t\x81\x04j\x18\xe3\xc0X\x8b\x88\x1d\n\xc0\u007fqxg4Wf\xf4\xc9\x10[\xf0\x9a\x8b\"\xb3ڒ\v`\x82\xefQ\xbaьUx\xa6\x8c\x99\xe1%\x16\xe2\x889\x18\x85!\x91\x19\xcd\a\xbb\xca\xe8\x92!\x9d\x01\x8c,\x8f\xca\x00\xe5J#\xc9\xd7חd\x10~\xcdX\x95c~\xe7\\\x81\a\xe3\xc4\x04\x97n\xa0\x0ez|z?\xd5\xd7[\x11F3\xeb\u007fԮ\x86i\x14]\x97\xc1\x96\x9cJt~\x9a\xe1\x9aG\xaf1\x12^\u007f\xc1f\a\n\xb5ir\xfd\xcf\xd77\x86\x99\x11\xa0\x9dA\xbbC( \x12\xeb\xd9\x0fyA5\x16\x91\xf9O.\xfaDF\x10)\xc9i\x84\r\x8d\xf7\xb8\x94\t\x91\x9e=\x16\xf0\xd0\xe2\xf7eBo\xd8?\x16\x1b\x16S_\xd9\x00\x87PnHoB\x8a\x0e\xe5\x95u\xd3#\xd31T0^\f\xe5\x0e\x9e\xf5\xc0\x1bJ\u007f/tY*\x94c\xa2Xˀ\x971\x13\xbb\x90\xa8\xbd\xfe\x8e\x89r\x10\xe2i\x8e\x10\xffn\xda4^0d6f\x86-\x1eȑ\n\xe9\xa7\xde\xd8f\xfc\x8aY\xa51fˈ\x86\x9c\xeev(\r\x9c\xf2@\x14*\x17\b\x8d\x13dܱ\x83\xd6j\x8f\xfe؛G\xc3H#\xa9v\xe6c\xa8\x1b\xe3ܷ2\xe11\x88\x1a\xdf\xcbZ\xb3\x9c\x1ei^\x11f\r\x1bᙛ\x0f\xa9\xf1\x8a\x19\xc8\t&\x0fpvf3`n8\xd1q\x94\x05G\x10\x12\n\x13\x1d\f\x9b\xf6\xe3\x99\xe6\x19\x9b\xf6\x96\x18\xdb/\x9c\x88ʊ\xa1\xf2C9g\xab\xd1\x017\xa3\xa0k\x8e\xb8Ȓ\x91-2P\xc80\xd3B\xc6\xc91\xc7d\xf7\xa4\xe8\xb5\x11*F4\\ףo&6\x01\x12\xac\xbb\u007f\xa0\xd9\xc1\xb9NF\x82,\x1c\xc8\x05*\xbb\xcaIY\xb2\xd3\xd8$a\x8e\xf3~\x90\xa9\x85\xde<3K\xbe\x0f/\xb6\xf8\x9b'A76ό\x96\xecR\xb6\x16\a\xd0br\xda\xff\x98\x84\rj\xff\f\xa1\xdd\f\xba^Vh\rI)*\xeb\x01aQ\xea\xd3\rP\x1d\xde\xceA4\x81G3\xfe\x1f\x981\xcb%~\xd3\xefyQ\x89\x9f\xe4\xca\x1cDÕz\xf8? S\xac\xb1x\xf0\xb6\"\x99!\xbf\xb6{\xdd\x00\xdd\xd5\f\xc9o`G\x99F\xd9\xe3\xcc7\xad\x97K\x10#\xc5ޙ\xa7 :;\xbc\xffj#\x93\x13F\xb7 s\x86\\\xec\x06\x1e\xcb\r<\x1f\x84r6\xd5nT̂\xa4\n\xae\x9f\xf0t}3\xd0\x03\xd7\x1b~\xed\f\xfcbuS{\v\x82\xb3\x13\\۾\xd7\xdf\xe2\x04%JbR3[\x90\x91\xea*\x9bX2x\x02\xa6c]\x85`\xdc\xdc)\xac\x93\xe4\xb0\x14*\xb2\xb7:\x82ʽP\xdae\x16;n\xe9\x92,\x168\x19\xf2\xd9+ ;W\a\"d\xd8\xe17j\xaf\x97p5\\S\xd3\x1a\xd6e\xf3}F\xcc\x015\x81\xd5u\xb3\x82\x9d>\xbdv\x9b\tv\x10\x92Y\xe7b\x16n)E\x86JM\x8bH\x82\xb6\x9eI\x12\xd6\tB\xe2\x02\x18\xb7}>\x9d\x94\fO\xbaCj\x88\xb4Е\u007f\xff\xb5\x95\xbd4\x8b\xdf\xfc='|K\xf1\x02\xbbf\x8b\x82\xf4\xebD\x92P\xbcs=\xc32\xf1\x80\\h \xf7\x95]\xea\xe9\x1e\xa4\x17\xa4\xef\xc1L\x17\x94o\xec\x00\xf0\xe6\xe2f\xbdV\x92x\x8e\xe3~\x17\xfa6D\xaf_\xd8՛\xea\x11\t\x9b\xb9\x97\xd8\xe1\xdc0\xcfm\x1c\xc5D\x90\\\xe8v:\xc1\xc0-E\xfeJ\xc1\x8eJ\xa5ۈ\xa6\nE5\xb3\xfa\x9bgi\xe4\xc4\xdfKyV\xe0\xf4\xc9\xf5l%\xb2\x0e\xe29Tی\x16&\xc4\x1e\xbb)\x84@w@5 \xcfD\xc5m\xfa\xc5,u;\x84c\x81S\xd0\xc9$KS\x10\xe6A^\x15i\x04XY\xa9\xa3|2O\xd3n\xfe\x81\xd0\xd8\xd6\xf0\xf0Y\xc86=V\x94\x14{:l\v\xd5I\xed\xb2\xa9\x82|\xa5EU\x00)\f\xe9SÞ\x9d\xabi\xeap\xbc\xael\xb2p\xad\x19\xd1\xc2,\xaa\x92\xa1N]\x91\xae\x86\xc9,\x13Es\xac\r\xb3\x97\x02\xc1\x81\xc0\x8eP6RJ2|\x16\xd1vI\xac\xe1\x95\xc5傈\xb4\xc1W\x96\x14\t\x89\xd8DgqZ[\x972\xddU\xbc\x97\x98\xe6\x9e\xcd%\xa5\x83{VJjdI\\\xdaC\xf3\"F\xf8釋6x~\xb8h3\xcf\x0f\x17m\xf4\xf9\xe1\xa2\xcd??\\4\xff\xfcp\xd1\xc2\xf3\xc3E\xfb\xe1\xa2M5\x9b\xd2\xd6s\x18\xb9\xf3W#?\xceb\x91\xb0==\x85\xe2\x04|_MየS+,7\xf1^\x91\x1ay_\x04\xbd\xb2շ1\th\x8a.\x1aSR\x97\\\x9a\x05\x12\xc4\xdb\x1d'\x99)\xc2\xfc\x86Z\xf40\xe89\xb5蛩\xbe\x97\xa9E\xf7\xe8\xf5]\xee\xcbT\xa2\x87\xb9\xc7O\xa1D \xfa\x02\x17WnQ \t)v\xb7\x9f\x9e\x8f\x8c\xd8\x1bl\x00\xf7w.\xa1\x1d\x94x%W\x18\x0f*\xbc._\xf6>\xc2\xef\x01\u007f\"\x10\xa92\xc2\xf0\xfd\x91w1Ulj\xd9'SdR\xe1ਉ#\xdbEY\xdd\x02\xb8\xefS\"\x97\xcaaj\xa5\xfb\x14\xbd\x86\x8a\xa5E\xb0\xefu\x05k,>\x95\xde6\xa4\x9d\x11\xdcD\xba̝\x12\x8c\xcc\xc7\x06\xfd\xeaij\x83\x14\\T\xca\xe7\t\f\xf4\xb76]\xe1\xb70m\xf9V\xa2R}\x03\aQE*\xad'h7Sw7^m\xe7\xf7\x96Q\x93\xe3\x9bu\xf7\x17-|\xed\x1d\xe7\xdd1G\x9fJ\x97\x14Zl\xe9\xa7\x13\x1ai\xd5yg\xd7\xe4uk\xeeF\x9c\xbe\xa5\x9b\xd0\xe9G\x0fҫ\xee\xa6\xcb\xe4\x96\xd4\xda\xf5+\xe9F\x81\xceWإ\xe4\xa2f\xaa\xe9Ψ\xa1K\xac\x9f\xfe\xe6\xad\xf6\x94*\xb9\xb3j\xe3fK\x8c\x13+⺵n\xd3 \x17\xd4\xc1%\x11g\xbe\xe6mq\xa5\x9b\xaf,\x9b\x9cGr}[\xa4rm\x12\xf0hU\xdbT\xbd\xdaL\x9e{X˖^\xa56\t\xdaV\xb0\xcdצ]\xae\x02\xfd\x12Q\xf5\xb8\xaa\x99\xad/\x9b\x8d\xba\xa7\xf1\x9b\xad [R76K\xb13k\xc4\xea\x1a\xb0\x91q\x97V\x86u+\xbfF\x80\xa6ԃ\x8d\xd4{\x8d@\x9c\xac\x02K\xad\xf2\x1a\x81=cv'\xa5d\xe2\xc7\xf8E\x1b0k\xdf\xd8\xef%Q\xe7NLȎ\xbb8\x17\xa2|\xea57\xbc\f^Ӵ\xfb\x19\xf3<\xa9>,w?\x8b\x8aiZ2\xbbAx\xa4y4\r\xa5\x0fx\xaa\xafM\xf8M\u0603\x93ۓ\x85\xf4\xe9s-\x9e\xeb\x9e\x13M\x14<#c@b\xc25\x98y\xe6\xee\x8a\xc9\xc4\n\x8d\xce7\v\xce_\bᯔ\xb9q\x12lφ\xc6\xf6P\xf4\x01\v\x03%\xdc,\xb1 \xfe\x9av\x10\x9d/k\xdf\xfd\xadBy\x02qD\xd9x\f3'\x93\xdcBS&\xba\tK\xdf\xeb\x0fwCQ\xcfqn\x16\x1c\xbc\xe5΄E\xc1\xf6p\xb4p̚g5\xaf\x8dz3q\xc0H\xd3x*UԽ#\xbf\xcf\xf9\x9e\xa9\xc7z^6tX\x1e<̚\xed\x17\t \xce\x0f!&@\xa6\x1e\xd3I\xdbҞ=\x96\xf3R\xa1\xc4\\0\x91\xecE\xa5\x1d\xbby\x89\xe36\v\x8e\xd9,\b*\x96\x85\x15\xc9dJ9N\xf3\"\xc1\xc5\v\x86\x17/\x11`\x9c\x17b̀\xec\x1d\x93I9\x00\x93T\xae\x91\xbcc\x99Rn1\xbf\xa98}\xb0%\xe1@K\xc2v\xe3\x1c\xa6\t\aW\x96\x1dXI\xa0\xe1\v\x05\x1f/\x14~\xbcD\x00\xf2\xb2!\xc8l\x102+9\x93?\x9f\x9d^\x172G9\xb9\x1b\x91*j\x93B\u058b\x17\xbac\xf6r\xf3\xe1\x065Ӫ\xe3\x9a\xc6R\xca\xf5y\xf2\f~\xa1\xdc\xefn\x1a\xa1j\xd9\xf1\xce\x16I\xe3X\xc43\xf4\x8d\xd7\xe6o\x98t\xfb*\nK\"\xed\xbe\xe7\xf6\xe4\x8a\x1d\xd4\x1aޓ\xecЃ~\x88\xc6\t;!\v\xa2\xe1\xbaޔz퀛\xbf\xaf\xd7\x00\x1fD\xbd\x8d\u07be\xa3EѢd'\x13\aD`^\xb7A\x9c'\x10QaR\xfe:D\u007f?\xdcL\xec\xf7\xd0m\x1d)\x0f\bW\xe3\x05\xb8*\x1e\xf8\x10~\x82\xfb/\xd6;\xb1W\x10e\xcduL\xde\xff\b\xd1_\xff\xb6\xa6\x9f/_(\xa0\xb4\x90d\x8f\xbf\nw\xc3\xe5\x1c\r\xba\xad;כz\xad\x11\nw¹\xae\x985\xf5wm\xf6\x805\xf5x\x83{\x16\r\x961u2\xb1\x12\xb5f3\x93y|\xfc\xd5M@\xd3\x02\xd7\xef*\xb7\xc1\xb5*\x89Th\xa8\x19&\xe6:m\xcd\u007f\x0f\xe29\x96\xe5\x10~\xce?\xf7\xf1\x96hk\xfel\xed\xc7\"쏝\xfb:\x03\x89\xe6D\xf4K\xbcW+Dk1ɭ\xf6\xa8\x84\x8e\xc1i]Yl\x93\x17\xf6\xcc\xdee\xaf\x10\x1b\xd3\xdfc\x97\xbaڋL\xe7\xafuu\xf7\x9d\xfaK\x9c}\xe5h%\xed\xfd_\xfe.T{_\xd6Y7\xbbn\xeb\xcd\xd2z+V\xbd\xd5\xda\xf8\x9a1\xff+\x82\xdeHߠյЄ\x01\xaf\x8a\xad5\x131\x95Rw\xb1۸\x93\xfb\xb7\xaeNo\x82q\x8eԔk\xdc\x0f\xf2V\xb1\xb9\xde\xf9B\xbfs\xe6Z\xf7M\x9f\xab\xaa\xb2\f\x95\xdaU\x8c\x9d\xea\"\xc3%\x13\x8f\xc0\xbc\x14)>\x10\xca\u03a2\x83\xeb8B\x047\xb7Q=\x9a\xc4f_݄<\x0f\x8bw`\n\xcccKo\x97\xd1\xc1\xb3\xa0s\xaf\xfc4\x01\xee\x86=\xec\xed\xe12o\x95,\xd4\xf7\xcb>\x13հ9\xe6Q6\xe0\\O\x1b\xd2\x19h\x98\x03\x1e\x91\x83\xe0\xb6t\xd4^,\xe7n\xb8\xef\xf7\x89@mC\xf1\xb5\xa9U\xc9\x04Ƀ\x81\vΛ\xbf\x15\xfdњoyD\xf9JM\xc0\xaco\f\x8e\x10a(\x99Λ\xba\x85\x9ch\\E\x81&\x99\xfe\xa8\xae\xcd\x14\xed\xea\xf9d\xa5u\xf7\xb0\x19\xeb9*\xc1\xa1A\x8c\u007f\x83\xfb\xa9\xbfQI\rg\x96\xaa\xa2\x863\x9bSP\x1du\x14\x99\\\xa3\xa0.>M\xbbVg\xaf\x0f\xb5\x8d\x9c\a`k\xec\xc3}ͮȾ@\xa5\xc8>\xdc\x1b\xfal\x1c\xb0=r\xb4\xfe\u007f,\xf1\xee2$MQv\xf7\xd6L\x97\xca%\x99\xae\x88\x1f \x94\xc0\xb4Z\xbd\x8a)`&\xf6\xee\xa6m\x1a\xbe3\x10<Ӆ4\xf9ZR\x99\xe2ɾ\xaf\x1b\x1a\xda\xd8]\x18ˈ\xe6\xbb\x10\xc8\xe8\x9e\x1a7\xd00iO\xe4\x96\xecq\x95\t\xc6\xd0\xea\xda!^/\xb9X}\xe9\xfbg$jvj\x1f\xdam}\xca\xcfq\xdb]:E\\5\x98\xfdL\x80\xa6\x12\x9b\xefn\f\x10\x12v\xe0E\x9e\xab\xa3B\xf4\v\x15CL\xdbm\xc3\x02\xf3z\xd5\a\x92\xfe\x83\x157>\x16\x8a\xa7u\n\xf2\x9b\x907PPn\xfe1a\xaf\xcdɅ\u038b\xf0\xb7\xd7\xc1\xce\xe0}o\xda\xd4'\x90Z~$\x86\x051\x16\xa9\xc5O\x9d\xac\xe0#\x0e\x03\vw\x90\x04s\x9b\x85\x8e}\x96\xc34\xd9\xf0{)\xf6\x12\xd5pU\xad\u0bc4j\xca\xf7\x1f\x84\xbcg՞\xf2\xc6\xdfX\xd4\xf8\x9eHM\tc'\x87O\fQ\xca\t\xa3\u007f\x8fq\xa7\xfd\xe3<\xa0Z\xddF~K@c\xec\x87whL\xedh\xb8\x11\x17\x04O\xd79Y\xf0͚\xac\x19\xe5Nv\xed\xa1\x95\xad\xa8tG\xf95\xca3\"\xc8a\xcc5|\x14\x1a\xc3f\f\xed\xc24\xe6\x02\x95^\xe1n'\xa4vI\xba\xd5\n\xe8·/\xb1\xac\f\xa1\xccn&\xbb\xefz\x00\xd5M=M\xb3\xdelfBZ\xb5a\xaf{,\xc8\xc9\x1d` Yf\xa2c|\xad4a\x11\x8d\xfcM\xe5\x8b6N4\xeb\x05\xf3\xbfD<\xc7\x01\xc17\xed\xf6\xf5-2\xb5=\xb6\xe0\x1c\xe5\xec\x013g\x8d\xa2\xb6\x19\xec\xb1#\xe4\xf0,\xa9\xd6\xc6\x02\xb4w\xdbA\x1b\x9d\xcf\x18(\xa3\x05G\xee\f\x9e\xb2E\xf6w\xe3-lƳ\xff݄D\xddx\xcc\xd9\xf0\x93\x13\x86-[K\x82\x91i\xb9\xeaz\xaaB_\xc3\xca\xec@\xf8\xde\b\x95\x14\xd5\xfe\x10\xe4rĖ\x8f%\xcf+\x83\x14\x94VC\xa8\xb0ө+\xc9[\xd9\xd3\xfa\xe0D\x83.ɞF1\xf5\xbb9\xe1\xdbR\xaf\xfd-\xc0\xab\x9d\x14\xc5\xca\xf3\xc2nP\xde\xf8\x8c\xa6\xa4\xc2\x04\xec\xfa\x10%9\xb8\x8fv\xf8\xeb6\xad\x18\x94%r \xca\xe3\x93p\xbaz\x9a\xadS)EM\xa4N\x8d\x83\x1e:\x8dgB \v9\x8e\xef\x83\xcfغS\xe6w\xfd\xaf|݀\xa2<|\xd6\xca僝((\x13\x19I\xb4ɵ\xe8\xde\xf3 \xa6\xe9D0]\xf4\u007f\xdf\xe0\xe5X\xdb\xc4\xf7)^\xf0\x97^\xf3\xde\xc9\x02\xfb\xf5\x96\xba\x89\xf7\\#\xf4\xf8\x13ݹ\xed\xf0\xcc`\xfd\xe7\xff\xf7\x13\x03\xc7$/\xebդ\x83e}\xa7\xdaS\x9a\xf9V\xcb=C\xe3\xf9(Į\xef\xf6j\x91\x93~\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 acb48c4d3..a5ce77793 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 36fc96706..3baea33fd 100644 --- a/pkg/cmd/util/output/backup_describer.go +++ b/pkg/cmd/util/output/backup_describer.go @@ -36,7 +36,9 @@ 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/collections" + "github.com/vmware-tanzu/velero/pkg/util/results" "github.com/vmware-tanzu/velero/pkg/volume" ) @@ -91,8 +93,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) @@ -660,3 +661,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 6797c80a6..a20f8d229 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 ed3f4d8c4..256b7258a 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 2e6c8edab..c6ef5939b 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) }