From d639c3555c4b7c31f1c710ed7bc6dc2d58958a60 Mon Sep 17 00:00:00 2001 From: Scott Seago Date: Fri, 1 Apr 2022 13:29:52 -0400 Subject: [PATCH] Add credentials to volume snapshot locations. This is analogous to the BSL creds work that was done previously, but for VSLs instead. Signed-off-by: Scott Seago --- changelogs/unreleased/4864-sseago | 1 + .../velero.io_volumesnapshotlocations.yaml | 18 ++++++++ config/crd/v1/crds/crds.go | 2 +- .../velero/v1/volume_snapshot_location.go | 9 +++- pkg/apis/velero/v1/zz_generated.deepcopy.go | 5 ++ .../volume_snapshot_location_builder.go | 10 +++- pkg/cmd/cli/snapshotlocation/create.go | 30 +++++++++--- pkg/cmd/cli/snapshotlocation/set.go | 24 +++++++--- pkg/cmd/server/server.go | 2 + pkg/controller/backup_controller.go | 13 ++++++ pkg/controller/backup_controller_test.go | 3 ++ pkg/restore/pv_restorer.go | 11 ++++- pkg/restore/restore.go | 11 +++-- pkg/volume/snapshotlocation.go | 46 +++++++++++++++++++ 14 files changed, 164 insertions(+), 21 deletions(-) create mode 100644 changelogs/unreleased/4864-sseago create mode 100644 pkg/volume/snapshotlocation.go diff --git a/changelogs/unreleased/4864-sseago b/changelogs/unreleased/4864-sseago new file mode 100644 index 0000000000..fdbe784915 --- /dev/null +++ b/changelogs/unreleased/4864-sseago @@ -0,0 +1 @@ +Add credentials to volume snapshot locations diff --git a/config/crd/v1/bases/velero.io_volumesnapshotlocations.yaml b/config/crd/v1/bases/velero.io_volumesnapshotlocations.yaml index 56ef139d28..65ebb5f3e0 100644 --- a/config/crd/v1/bases/velero.io_volumesnapshotlocations.yaml +++ b/config/crd/v1/bases/velero.io_volumesnapshotlocations.yaml @@ -43,6 +43,24 @@ spec: type: string description: Config is for provider-specific configuration fields. type: object + credential: + description: Credential contains the credential information intended + to be used with this location + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must be defined + type: boolean + required: + - key + type: object provider: description: Provider is the provider of the volume storage. type: string diff --git a/config/crd/v1/crds/crds.go b/config/crd/v1/crds/crds.go index 54838c3551..0d508e67ae 100644 --- a/config/crd/v1/crds/crds.go +++ b/config/crd/v1/crds/crds.go @@ -39,7 +39,7 @@ var rawCRDs = [][]byte{ []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec\xbd}s#\xb7\x910\xfe\xbf?\x05Jq\xfd$]Dʛ\\\xf2\xbb\xdbJ=)eWvT\xf6jU+e\xfd\xa4\x1c\x9f\x0f\x9ci\x928\x81\xc0\x04\xc0P\xe2\x9d\xef\xbb?\x85\x060/\xe4\x90\"0Ծ\u0603\xab\xbax\xa9\x99\x1e\xa0\xd1\xe8wtӂ\xbd\a\xa5\x99\x14/\t-\x18<\x1a\x10\xf6_z|\xffoz\xcc\xe4\xf9\xf2\xc5\x17\xf7L\xe4/ɫR\x1b\xb9x\aZ\x96*\x83\xd70e\x82\x19&\xc5\x17\v04\xa7\x86\xbe\xfc\x82\x10*\x844\xd4\xfe\xac\xed?\tɤ0Jr\x0ej4\x031\xbe/'0)\x19\xcfA!\xf0\xf0\xe9\xe5W\xe3\xff\u007f\xfc\xd5\x17\x84d\n\xf0\xf5;\xb6\x00m\xe8\xa2xID\xc9\xf9\x17\x84\b\xba\x80\x97D\x816R\x81\x1e/\x81\x83\x92c&\xbf\xd0\x05d\xf6c3%\xcb\xe2%\xa9\xff\xe0\xde\xf1\x13q\x8bx\xe7^\xc7_8\xd3\xe6\xdb\xe6\xaf\xdf1m\xf0/\x05/\x15\xe5\xf5\xc7\xf0G\xcdĬ\xe4TU?\u007fA\x88\xced\x01/ɵ\xfdLA3ȿ į\t?;\xf2\xb3^\xbep \xb29,\xa8\x9b\x0f!\xb2\x00qqs\xf5\xfe\xf7\xb7\xad\x9f\t\xc9Ag\x8a\x15\x061\xe3\xe7F\x98&\x94\xbcǵ\xd9\t\xe0&\x103\xa7\x86((\x14h\x10F\x133\aB\x8b\x82\xb3\f\x91XA$DN\xab\xb74\x99*\xb9\xa8\xa1Mhv_\x16\xc4HB\x89\xa1j\x06\x86|[N@\t0\xa0I\xc6Km@\x8d+X\x85\x92\x05(\xc3\x02b\xddh\xd0Q\xe3\u05f5\xb5\x1c\xdb座Hn\t\bܔ=\xca \xf7\x18\xb2\xb35s\xa6륭/\xc7/\x89\n\"'\xff\x05\x99\x19\x93[P\x16\f\xd1sY\xf2\xdc\xd2\xdd\x12\x94EN&g\x82\xfdw\x05[ۅڏrj\xc0\xefw=\x980\xa0\x04\xe5dIy\tg\x84\x8a\x9c,\xe8\x8a(\xb0_!\xa5h\xc0\xc3G\xf4\x98\xbc\xc1\xed\x11S\xf9\x92̍)\xf4\xcb\xf3\xf3\x193\xe1\xfcdr\xb1(\x053\xabs<\nlR\x1a\xa9\xf4y\x0eK\xe0\xe7\x9a\xcdFTesf 3\xa5\x82sZ\xb0\x11N]\xe0\x19\x1a/\xf2\xdfT\xdbvܚ\xabYY\xca\xd3F11k\xfc\x01\xc9|\xc7\x0eX\x82w\xb4\xe4^u\xab\xa8\x11m\u007f\xb2\xd8ywy{פ3\xa6ױ\x8fxo\x10_\xbd\x05\x16aLLA\xb9MDj\xb30A\xe4\x85d\xc2\xe0?2\xce@\xac\xa3_\x97\x93\x053v\xdf\xffY\x82\xb6\x04-\xc7\xe4\x152\x152\x01R\x1695\x90\x8fɕ \xaf\xe8\x02\xf8+\xaa\xe1\xd97\xc0bZ\x8f,b\xf7ۂ&?\\\u007f\xd8a\xad\xf1\x87\xc0\xbc\xb6\xec\x97?\xfd\xb7\x05d\xad\x13c_cS\u007f\xcc\xc9T\xaa\x16s\xb0\xaf\x8c[@\xbb\x0f\xad\x1d\xee\xf4[\x0e\xb6\xfe\x97\xb5\xa9\xfc\xa5z\xd0ҏ\x9dD)\xd8?K@\x16\xe7N,l\xb0\x94\r\x90$\xcc\x0f\xc9b\xbc\xf1\xf7-8\xb5\x03\x1e3^\xe6\x90W\xdcvc-k3\xbe\xdcx\x01\xc5\x11e\xc2ҿe\xffvڢ\xfe\xabe\xa7\x1d3\xa6\n\x88\xa5@&\x1c<\xc2\x04.\xb6\x13\xd3v0\x03\x8b\x8e\xc9\xed\\\x1dA9G'\x1c^\x12\xa3J\u0602\x19\xaa\x14]mAL\x90\xcd\xfb\xe2\xa5z\xde3\x04\xce2h\n\n\x87\x1a'd\xa8ڜ\x11\xf9\xa4\xb12\x97\xf2\xfe)L\xfc\xd5>S\xf30\x92\xa1\x8eC&0\xa7K&\x95_\xbb\x17)\x13 \xf0\bYiP\xcco\xc0-\x91\x9dJE\n\xa9\xcdv,l?\x89\xc4\x1d\x8em[\xb8\x13\x85\x1b+\xf3\x8c#l\xb1]h\x8b\x89H\x01v\xae\v{\x12\xebg\x95,ݳ\xebܾ\x81\xf0n\x8c\x90\tՐ\x13\xe9i\xa0\xe4\xa0\xfd\xb7rdO\xf5);\xdb\n\xbaZ\xbc\x93\xbb\x9cN\x80\x13\r\x1c2#\xd5&&\xf7\xc1\xa7\x1b\xfbp\x8e-x\xec\xe0!\x9e\xf7zN\\/l\aHb\x95\x8e\x879\xcb\xe6N$Z\xdaD8$\x97\xa0\xf1\x18Y\xb5m\xb5m\x91䩽\xf7\x1f\xd9u\x90\xea\xf1đZ\x87\xd7u\xb8\xea\xb1\a\xf3\xa9\xc7\x13l\xa8\x8d\xd9Z_\xed\x94#\xf5\xf8e\"6\xf0\xd5\x04\xa2\xbd\xdax\xf5\xb0D\x8b&\x86U}\xaf\xa6\x04\x16\x85Y\x9d\x11f¯OA\xa4\x9c7\xbe\xff\x19oL<\xc5_\xad\xbfyP\x8a߹+OA\xb4\xbbR}\xfe3\xdc\x14\x14\x16\xb7^V\xec\xbd!\xdf5\xdf:#lZmH~F\xa6\x8c\x1bPk;\xd3\xeb\xbc\x1c\x02\x19\xfb\xc8;;\x16\xd4d\xf3\xcbG\xab\xd9\xe8\xda\x1d\xb3'^\xd6_v\nbИۂ\xf9\t\xb8\x04\x8d9\xa6`\xe1\x8c\xc4;\xc4f\xfd\vj\xd7\x17ׯ!߅\x1e\xb2\x1f\xe5m,\xe4bm\xb2\xcdO{\xadw\xdfexէ\xb2 \x9c\xf9\u007fF(\xb9\x87\x95\xd3X\xa8 vs\xa8\xfd\xd0\x16[b\x139\xe8\x87@\"\xbb\x87\x15\x82\xf1\x8e\x85'\xdfޗ\x14ܸ\x87\xd5>\x8f\xad!\xd0\xceɛ{\x0e\x93\xf6\aD\x04\x9a\xa1\xfb#\x8f\xa0\x93(\xf0\xa2\xa7\x17G\xf6g$a\x04\xdc',\xb3ڶ\x863\r7\xf6X\xbb-\xb2\xa7`Ί=\x17\x8a\xbe4\rxZ\x82\x9b\xe8=\xe5,\xaf>\xe4\xe8\xfeJl׆\xdb\xe3Z\x9a+qF.\x1f\x99\xb6S\x139y-A_K\x83\xbf<\v:\xdd\xc4\x13\x90\xe9^\xc4\xe3%\x1c۶xh\xfa\x9b\xf6 n7\xae\x9c[\xa1\xda\x1e\xa6ɕ\xb0\x86\x8b\xc7\az\x0f\xdd\xe7vˇ\xf6X\x94\x1a\x1dJB\x8a\x11\x8a\xcaqח\x1c\xb2\xf7\x04)UkG6\xa7V}\xd4}pO\xb0wV\x92\xb8\xf7\x9d?\x94\xd3\f\xf2`m\xa2\x17\x8f\x1a\x98\xb1\x8c,@\xcdv\t\x8e\xe6(,\u007f\xdfo\n{r]7\")l?\xd1\x1e\x86g\xdd\xf9ӓ\x19ٓ\xbb\xc7Sa\xb3\x9f|t\x8b\xf3n\xfb\xa3O\xaf\bE,\xea\x1fOb\x97\xe69FZ(\xbf\x89\xe0\xf8\x11{\xb1)\xfb\xddĜ\x84\\\xd0\u009e\xdf\xff\xb1b\x0e\t\xfa\u007fIA\x99\xda\xe3\f_`ЄC\xeb]\xef&j~\xc6~\x81ib\xf7wI\xf9\xa6[\xb8cq\xd2\xf2\x16\xe0N\x90\xcb\xe9\x86\xc6rF\x1e\xe6R;\x99:e\xc0\xbb\\6\xed\xc149\xba\x87\xd5\xd1\xd9\x06\x1f8\xba\x12GN\xc0G\xb3\x9bJ[\x90\x82\xaf\xc8\x11\xbe{\xd4G\tړ\x12\xf7zLt:}\xeb\xd1\"\x8b\xa6\xe3\xb7\xf6\xf8z5w\u05ec\xf7\xa2\xc3Bj\xf3\xd7n\x87ݖ\xf9܄7ںi\x87\xdf\xebI\x9d\xdd\xfb\xb0*\xa6j5\xb9\xa9\x01\xe5\x9dx\x8e\xd1\x06\v\xa0\xa7m\xf4\x94\x93\xaer\xd0\xd1\xcaQn\x11\xfc\x04U\xb8\x00\xc0>S\x8c\xd1\x1a-^\"\xf5\xed\xcbdž\x8fўP\xfb\xef\xe6B\x0e\xad\xd5fr\xb1\xa0\xeb!\xaf\xbd\xa6\xfaʽ\x19h\xda\x03r\xbb\xaff%\x9e\xcb\xfdս@C\x18\xecz`f\xce\x04\xa1\xe1\xf8\x83\xf2\x04EI!\x9f\xe6Dn̩&\x13\x00\x11\xd0\xf7$kp\xe3y\xe5\xf5\x82\x89+\xfc\x00yqp\xf9Njt%mg@u\xb5\xa1\xd5\x0f(q\xf6U\x8ddN\x1e栠E\x15\x9b\x0eo\xab1\xee\tRH\xd3\xf4+X\xb8\x85̏5\x992\xa5Ms\xa2\xfb\x12\\\xa9\xf7%\x87\xc8\x1d\xb6\xab\xbbc\v\x90\xa5I\u0603\xcb\xfa\xedV\xb4rA\x1f٢\\\x10\xba\x90\xe5\x1e\xc2\xdd\r+_آ\n)\xfa\x1dx\xa0\xcc \xbb\xb3p\xd1\xc3b\xa4ݥ\x82\x83\xd9w\x8b'0\xb5\xec(\x93B\xb3\x1cT\by\xbb\x9de\xd2\x1e\xdc)e\xbc\xec\n\xdft\x8dX3U\\*\x95d\xa5\xbeuo6\xbc\x86s\xf9\xd0F\xd0\xde(\x98\xd3%\x106%\xcc\x10\x10\x99\xdd\x17P\x8ee\xe3'<2\x105{\x93\xe5~\f\xde\x0e\x10\xe5b?\x04\x8c\xf0d3\xb1\xd3)\xd6|\xfck\xca\xf8sl\x9b\xa5\xbc\xf4\xa3\xf1}\xfd\xf6\a9\x1a\x15S\xd9_\x84M\x80\xbc\x03\x9a\xaf\xc2\xf9\xa0\xc6XS\x15i@\x12U\x8a&G|\x86\x93\x11c\xdf\xf9Y\x1c\xd2pc\x82\xed\xb1\xb1k\xfe|f\x9aڎ\x05\xf1\xacڎ\xfd@%\xe8R\\3W-\x00VT\x06\xc5\x19\xe7^QM\x84\xe63\x01k\xa0B\xee\x9c^V|z=\xda%\xf2l\t\x83w\xae.FuYs\xf3zC\xb3\x91\xfc\x16}\x04\xbc\x83w%K\xf2@\x85\tD_)s\x85ܓ\xeacw\xd5\r\xaaf\x11Ood\xd6\x05\x955\xa4\xb7\x810j\x85\xe9V\xfbN\xda\rk\x9a\xe62\xbb\xb7\xeaȂ\xce\xe0\xf8X\x93Wo^[R\xb1Z\x87\x15\x19\x11\x12\xc1\r\xe6\"\xb1\x85\x92K\x96[\xd5\xe9=U\x8cN\xb85\x82\xa7\xa0@d\xa0ɗ'\xef/\xde\xfdt}\xf1\xe6\xf24\n\xb85\x9dᱠ\xc2\xd2`\xa9\x834\xafv\xdf.\x00Ē)),\x82\xe2\xb0q5%\x94,\xc3l\xb3*\x13͚Z|鵹(\x88Պ\x83#\x84\x89\xa24\xc1;\xfa\xc08'\x938\x88\xa5\xc8\xe6T\xcc,^_\xcb\xd2\xce\xf3\xcb/\x11+\n\xf22\xf3\a3\n\xa2?L_\x9e\xf9p\x16\xe5\\>h\x94-\xa03Zx\x1cG\xc1ll/\xd1+a\xe8\xe3K\xc2\xc60&G_6\xfet\x14\x05\x13\xb1U(i\x97\xe9\xe2\x11\x0e\x8b\x9c\x19P\x94\x93\xa3&不\xbf\xb4넼I\xa0\xf85\x01KP\xce\x0ep$\xb7\xaf\x03\xdf\r\x053\xaar\x0eZ[\x9e\xfb0\a3\a\xe5\xddJ\x9e\xc8 \xc6\xeb\xec\x86T\xf6|ufJֹ\x91Q\x10C\x1e\xe5}\x95\b7T\xdf\xebs&\xacH\x1d\xe5\xd4\xd0Q\x83\xe9\x9e;i8\xf2\xf2y\x14,\xe9Qu\x1c\xcf\u007f\xa3J!\x98\x98\x8dh\xf5\x14\x13#:\xd2s\xe0\xfc8b\x96Q\xe2\u008dh{\xb7\xf9ZL\x80!\xd21\xe1F\x9b\xa3_V\f\xdc}yL\xae\xa5ٕ\x81\xb6}T\"\fq<\xee\xe4\xf1\x97\xd7w\xef\xfe~\xf3\xf6\xea\xfa.\x96\xb57\xc5\xc2vV\x9f\xc6$[b\xa1\x83\xd5\xc7\xed\xfe.\xb1\xd0f\xf5Qp\xb7\x88\x85\rV\x1f\x87\xd8\x0e\xb1\xb0\xc9\xea\xe3X\xf0\xa6X\xd8\xc2\xea\xa3\xc0\xae\x8b\x85\xad\xac>\nj[,lc\xf5Q \xbb\xc5B\a\xab\x8f\x17B\x9bb\xa1\xcd\xea\xe3 n\x17\vk\xac>\nl\xb7X\x18X}\xc7kq\xac\x1e\xc42\x99\xcd\u007f\xe7ͯ\x06+\xaa\xf6<\x8e\x0e\x8dČ\x03&\xda|\xaeK+x^̷]\x82b\xf9\x9e\xb6\xd3*Ds\xb1Q\x90I}\x1cB\xc66\x8a\xb5ʢ\x8dc1)V\x9a\x1bOEκ\xc7f<\xcdߚH\xc7\ai\xe0dL\xde\xf8\f\x03J^\xfdt\xf5\xfa\xf2\xfa\xee\xea\xeb\xab\xcbwqH!\xe9g\x87\x84\xa4\x91\x9e\xa89\xee0\x0f\x13\xf0\xb2[s\x88\x16\xc8n\x14\n\x96L\x96\x9a\xaf\xaa\xf4\xf6\xfeG\u05cd\xf5\x93\xebS\xcaVD\x83Z\xb2,e\xb6\x9dS\xeb\xa3\xea\xb8\xf1\xa4\u0093\xbe\xfa'Ԟ\x04\xc0\xdbmb\xaf\xfc\xa4\x90\xd6!-c\x0f\xf2\x19\xecc7\x9e\xb0\x92\x13 \x1eV\x81j\xccr\xa7\x1a\x95\x00t\xb7\x8dM\xf6N\\l\x0eT\xbf^Ô\x96\xdcyێ\x8e\xc61\xba\x8c\x1b}Y\xec\xd7J\xee\x19@i\x8e\x16\x9b\xbdu\x97\xbcB\xc4\xe00B\xe8\xd8'ƶ\xd4\x0e\x1di\xaf\xba\xc1|\xeed\xb0)\xa3\xf2\xe6\xea\x91.\xe5\x89\vIO\xd9\xec\r-\xbe\x85\xd5;\x98\xa6\x80XG;\xe6\xcc\xfa\xf4\xd2XӠ\x1e\xa8\xf5\xb8\xa9\xa5pžx!1\x19\xc5]\xa3\x85\x93;\x9f\xfd\x8c:\xacEOڒH\xbf\x83\x15F\x9av\x17F[\x95i\xa8y\xc9\x10+\u007f\x88\xd9\xd7pˤȠ0\xfa\\.\xad\xee\x00\x0f\xe7\x0fR\xdd[K쁙\xf9\xc8\xc5\xc3\xf49^\xc39\xff\r\xfeO\x8f\xd9ݽ}\xfd\xf6%\xb9\xc8s\"\x91Ֆ\x1a\xa6%wiw{g\xfav\x8d\xba\xa8\xc0\x19^l?#%\xcb\xff\x1c\xcfl\xc38\x00m\xc8\xc2eb\x1e\x88>n1\x92\xbf\nR\xaa\a\xae,\v\xaf8\x02\x91\n\xc3o\xfb\xa4\xc1n\x1f!a\xd9+\xba=\xd1>\x91\x92\x03]/\xe2\xb0\xdf\xd8?4\xdc5\xf6K\a\xee\x1a\x11\xe1㮁'\xe00R\xe3\xb8\x16\x1b\xfb\xa5\xb3v\x0fop\x162\u007fItY\x14R\x19]\x15,\x18[F\x10\x17ϨG\v\b\xde\xed;#\xffY\xfd\x88wG\xf4\x0f\xc7\xc7\u007f\xfa\xf6\xf2\xef\xff\xe7\xf8\xf8\xc7\xffL\xfdN\r\xb3Qk\xe6\x10\x80u\x01\xd9X\xc8\x1c,\xcb>s\xff\xf4\x96\xd7E\x86\t2\xd7=У\r5\xa5\x1eϥ6W7gៅ̯nz\x82D\x18:A\x05%\aQ\x02\xb6\x15~\x89\x19-J\x0f\x05bz\vM_K\xc6\xd2\xfb\xd7\xf6\xc8\xdcP3\xdf?Ůk<(f\f\b\xb4UA-4\x91\xd33\xcb\x1d\xd1\x14\xe8û%9Z\xbe\x88\x8cP\xb6\x00\xf4\x17lӀ\xa2\x03m#b۳\x9b>\x1c\x8b\x04צe\u007f\xc1KPeS\xf6\x00zqs\x15\n\x0f}D\xc4\xf7\x95lն}\f\xf9\x16\x12ο~\x169\x17\xa0\xf7\x13uuN\xb1\xbb\x83\xb1\xdfM\xde\xed\x833\xacPDE^W):q?\x8e\xb3\xa2Le\xe6\x1e\xc2\x02\x16R\xad\xce\xc2?\xa1\x98\xc3\x02\x14\xe5#m\xa4\xa2\xb3d\xf1\x13\xa6\x8aS\xac\xff\xe5>\x97\xca\xf9\x1b(\u061ci\\\x12O\x03\xaa\x02\x92\x95\xcaZ;|\x15t\x14\xc8?\x9a|\xab觻DҾ\xa3M\xe4u\xb2z?[\xb3\xe6\x1f\xe8\xc6YJ^.@\x9fUVJ\x0f\xc0\xe8\xd2\x14K\xb2\xa4J\u007fT\x8b+gK\xa6\xf7M\x97\xee\x1aT\xac\xde&\xb2&\x82<\xd6-\x82\t\x03\xb3\x1e&\xda\xe8\x10\xc8\xe84\x1f}\xf9\x88\x1e\x9b-KS\x94\x98<\xbc\xa0\xa6\x8aJ=\x162\xcds\x17F\xa3\xa0O\xdet\x98\xbeHqc\xbbQPc@\x89\x97\xe4?N\xfe\xf1۟G\xa7\u007f>9\xf9\xe1\xabѿ\xff\xf8ۓ\u007f\x8c\xf1?\xfe\xe5\xf4ϧ?\x87\u007f\xfc\xf6\xf4\xf4\xe4\xe4\x87o\xdf|sws\xf9#;\xfd\xf9\aQ.\xeeݿ~>\xf9\x01.\u007f\xdc\x13\xc8\xe9響L\x9e\xf2\xe3\xa8\xf6Ќ\x980#\xa9F\x8e\b\x9e,\xf6\xb0k\x04\xe4\x1e\x8a'\xbd\v\x9aH_\xc1K\x9a\x1a\xdbGd\x1d}U\xab^h\xe8\xa9Yi\xc8\x14\x98O\xcf\xe7\xec\xe6\x15\xd4pw\x8b\xa92\xf8\u007f1n\xe8\xfe\xa6\xa7CSm\xb7`\xb1C\x82\x01\xfa\x1e`1\xb4\xbf\xc4:\x12\xfe\v\xf7\x90\x10\x11\tcp\x95\x0f\xae\xf2m\xe3\x97\xee*\xbfu\xe7\xa7\xf6\x93\xa3\xb7\xbb\xdf\xd9\x1c\xfc\xe4I\xd2.\xf9\xe5\xb4պ\x9a\xdcQ\xaf$\xce01\x9706\xb4ߙOX\x17\x92#\x85,JN\xf7\xbe\x1d[\xcdc3sh3\xb90\n\xa6\x17\xafua\xd0:/ݥ\"D\x1f\xc1\xcd\\7r\xc19a\xc2\tI\xfc\xd8\x03\xe3qv0\xa659\xaf\x03\xa1._qi\xd1\xf00\a\x91t\xb7\xd2\r\xa6\x896T\x19&fc\xf2\xbd\x85\xe5\xb41\x9f\x8b\xc2\x04Y\x94ܰ\"2!\xa9\xb2\xb0\xaa\xda$\x84j-3F\x8d\xc7p\xb4@\xe5T\x9b\xb0%\x98\x96c\xe8=f\\f\x90\x83\xc8\x00kY\x95\x91r0\xec\xf9de1z)\x96nn\x94\xe4\xa5K)\x86h\xee\xd3=\xb7\x8f\x9d\xeej\x8f\xafO\xad\xa9\xb3^#\x99\"\xfa\xb8\x1d\f9\xadK\x89U\xf1\xdd8x\xe9*v\x95\xfd\x92d\x86l\xe8\xd6u|\xbaҌS\xa2\xaaJ.>p\x16P\xba\x9a\xbbUŭ\x15\xd5D}\xe1SSo\x9fE\xb5=\xa4Z\xdbS\xa5\xed\xa7\xce\xeeRe{X<\xf5\x89:D\xb2F?\x05\xb4\x87\x12X(\x98\xb2Ǟ\x1c\xe6BT{DX\x0e°)K\xb2\x13\xacΤ\xa0\x00\x81i\xc2@\xb3\xb9+\x83)\xdaI6)4\xfd\td\xe8;\xcf\xc1a\x18\xfa횟c\xe0\xe6\x037\xdf1\x06n\xbe{\xf8\xe3\xf4\x19\xb3\xf2\x0fh)\xe3\xcd\xe5\xf4\xebկ\x1b\xf7\x9f\x91#<\xc7]\xf9\xea\xbcօU\xce\xf1\x8bq\xc7\x12\x8b\xc0\xe2ѳVd%\xe4\\1}\xf9@\xe6l\x16\xeb\x11\xe3\xb0\x04\xee\xf5{\xb2\xa0\x82\xce\\)M#C\xa8.\xf6v\x84eI\x8a\xe5\xad\xc2k\xb8T+8-\x9b\xe2\x92\xc6\xd1r\xdd;N\x13\xce\ue07c\x86\x82˕\xaf\x98)rrk\xa8\xb1l\xe9\x16L\\\x02\\\x12\xf3\xc0\xd5ܔ\x9c\xdfHβ\xa8\x98C\x9b\xf4\xae\x90抒sR \xa81y+ 6,s\xc1\x1f\xe8J\x9f\x91kX\x82:#W\xd3kin\x9c\xb9Y\xdfO\x89;\xbc\xd2\x03%lJ^\xba\xfeh\xc4\xd0\x19\xba.\xaa\xfauqD\xa1Z\x13s\xc2\xe4\x81\xe9\xbevz\xb4\xc0\xdc8\x80\xbf\xc1\xafZ\xd1\xe9\xfe\xfd\xec\xe4\xc3\xd9\x14\xb2U\xc6\xd3y\xd6E\x86ɮu\xf9\xf5\xfa\xdcƹ\x8cV\xda\xc0\"\x94\rC\a\n\xc32\x93\x85\x14\x1a\\A\xbd\x14\x0fW\xb5B\xe70\xd3=\xf78U\xc9+\xa46\xb7\x86\xaa=˴գ}Jo\x02\x18K\xfe\x19\xe5\x1cr\xc2\x16\v\xc8\x195\xc0\xe3\xfd\xe4\xa1\x02h\xb3ܣkw\xe9\x8aI&\xe9\rs*r\x0e\n\xeb\x15z\x1f`\v\xbe\x01\xb5`\x82\xc6\x16\f!Uz\x17\xba,!'4ˤ\xca}-\xb8Pً\xaax\x8d\xbf\xe2x\xa8+5$\xcfz\xbe^4\xe4\t\x97ٽ&\xa50\x8c\xd7\xe5!CmHߨ1\x1aj\x12\x8b\xa9\xfesT\x9d\x89\x11\xf6#;\xffM\xfd'\xfc!V\xf9\xedc\xf9\xecW\xcfws\xacՠ\x04$\rL\xa6\x94\xf1b+\f\xcc\v\x96V}\xb1DU\xd7W\xad\x04M\x9a\x91\x81\x05\x88\xdb]u(\xb2M\xac\x8bF\xef#\xab\x90\xb8\xd17G!\xa1\x16Ps\xec([\x9c\x1ck\f\x85m9\x13Ь_̰&jz\b\xb3y\x82\x1d?\xf2\x16jz\x10\x98)\xec1\xb2jԶts\xef\x93̯\xa44\xe4\xe4\xf8\xfc\xf8t#\xa8u\x9c\x0eu\xca88\xe9\xea\x8a,e\xd5f%\x83\xd4lQ\xf0\x15\xee\xcfq\x8e\x1d\x9d\xfcuXU\xa6ň\t25\xbbˡ \xd4\x19ђ\x18EC\x97\x81\xf4\xb9Zh\x16\xb8Q\xa5\xd7UN\x8e\u007f>>#`\xb2\xd4|`B\x1e\xa486HFcr'I\xa9\xeb\x89'\xc3\\ɒ\bpu\x00\xe0\xb1\xe0,c\x86\xafP\xcc'Ô\xa5q\xc5\x17\xb1A\"\x16ں|d\xc6\xdf\xd3I\a;%_\xe1iw\xaa\x02\xa1\xd6\x18Z\xc2\xf9\x1c(7\xf3\xf4\xfb}\x96.\x85\x14\xa3\xff\x06%\xb1\x8c\x97\xf0\x10S\xbd;\t\xb1\xb3\xe68@\xc6I\x8a\x1ba\xfd\xed\xc4$\x06\xab |\x03\xd1*'\xd9\xe8Hzww\xf3\r\x98\xb6\bKB\x87\x9dQ\xc8\xcfG\x976\xa8\xa9T\x1d-w\x9f\x1e}\xe5\xdf\\\xea$̐\xcd~\xadڸ\xee\x13\xceH\x11i>g7\x8cl\xa7%\xfb\x8cFru\x93\x9e\x88\xf5wYZlM脯\xaa*\xb2\x1a\f9\xb2SOO{f\x02\xf7\xf3\xaf@s\xac\xdb+\xb4\x01\x9a\xa8\"\x1d\xe0\xa85\xe6r\x18\xa5\xc6\xf5ݝ;\x90=v\xb4Y\x02\xcb\xd3\xfe\x18\xcfT:\x9bt\x15^\x14\x14\x8e\xfd\xfa9~$&\xb9\xc1+\xdc.\xf8\xdf'\xbdr\x13ih\u007f\xec\x96\xe8k;'\x16\xef\b\x83\t\x9c&\x1e\x8a\x1e\xb3\xeb\x9f%Lzg\xab\x92\xae\b\x98\xc3U/\x98\xfe\xeee|Z\xda\xfa8\xc8\xfd\x92\xe4\x12^\xcd\xf1\x9ch\xc2\xe9}|<\xf5K\xb5$i\x89\x88\xed\xd7\xfba\xa2\xe7\r\x05\xd2[\xdf\xc2\xcb<\xc9\u05cd7/\x1b\x1bIh\x96\xa5\x15\x8ar\xc3w/G\x86\xa5A-c\x13\x1c\xebћ\xc4\n\x19\xef\xbf\f\xa3ׅ\xb7\xc3\\w;\xc8e\xb7\x8ez\x89\x8a\x88r1\xe9\xc1I\xaa\x02\x18\xca\xd4\x04\xe37\xbe\x873\xa5*\xb6y\x8d\xd3\v!\xdc>\xfa\x1e\xaa0T̀\xbc\xb03\xfd\xe3\x1f\xfe\xf0\xfb?\x8c\x11\r\xc9PC`\x99\nruq}\xf1\xd3\xed\xfbWX\xc4-\x95ʟ\xe5f\x1b\x96mH\x96?\xed\xc8<\x82\xb2\xd8+5\x16:\xeb\xb3\xc3\xd6\xd6\xf0\xfeo\xe7\\֩q\xb6\xe60\x12\xd9\xcdG\xe23}\x84\xd8\b\x0fч\xb6\xb3MV\xdc\xca\xec\xfe\x00\x96\xf6\xf1ݫ\x1b\a\xaa6\xb6\x93v\x81\x8a\xe0bfb)\xf9\xd2\xf5\v\xbc{u\x83\bJ\xdbY\xfb6\xc6\a\xd0շ\xb2s\f7\xe1]jN\x12T\xb6(|\xc7LJ\x14Pδa\x19~\xab\nS$\xda\xf7\xf2>%\x8b\xe7\x93\xf1+\x1c\xbf\r\xe9@\xe8bH>\xcdk\xae\x89\x96\x8b\xa1\x0f\x8bh\xb8&R\xaft\r\x1a\xc9\xc15\x12'\xea\xa5\xea\xa7\xc7\x0f\x1aɧ\xad\x91|n22\xf9\xd5B\xc1\xad\x91EϬ\t\a\xe4@9\x13\xa1\x13ݶ\xa4\x06\x92'l\xa9\xeb\x1d}qsUy\xc7e+\x11\x01\x93W\xa2\xa1\xea2\x9b\x87،\x00\xad\xcf1=\xa2,\x9c\xe7+4\x94\x8c\x8fX\x15\n\xb0\v\x9f\x14gUE\x02D\a\b\xf7#\x98,\xfe\xb4\xa0O\xc6\xe7\x8e\xf8xbخ\xbei\x18\x99\xa2z\x0eة\x02\x1e\x99ѡ\xdb5\xd5R\xb8\x10\xae\xdf>&\xe3\x03\x98L\x93\x82j\xed\x02w\xa6^\x84\xfbȍ̏\x13\xa2\xb7\x8d\t\x91\x99\xa2\x19\x90\x02\x14\x939\xc1\xaa\u007f\xb9|\x88\x9f\xe7\x04fL\xe8@\xbfv\xa2\xe1`X]\t\x92\"\xc2u\xe7\xd9w\xad.Rخ\xbc4\x99L\xe0\xc3\xfeu\x8f\xc5\xf5\x04\xa2諓8M{|J\xca\xf9\xaa>\xa8ᦧ9\xfc&mf\x12\xa5\"\xa1^\xf7z&Q|4\xb0\x95yd\x8fB\x9d\x95ԇ\xfc[\xd4ɴ=UټG\x9b/\x12\x9f\xbe<\xa46=9\x86Ԧ\xbdǐ\xda4\xa46\r\xa9MCjӐڴ\x17\x88!\xb5\xa9\x9aѐڴc\f\xa9MCj\xd3\xd3cHm\x1aR\x9b\xea1\xa46\xed5\x86Ԧ=Ɛ\xda4\xa46m\x1dC qHm\xfa5\x06\x12\x87Ԧ\xb8ׇԦ\x881\xa46\r\xa9Ma\f\xa9M\x91c\xd0H\x86Ԧ_\xa3F\xf2\xb9\xc9\xc8^\xd5\xc5\"_\vy<7JNz\x94\x19\xbb\xc1X=\xcb|\x1a\x90\x9c&\xd7\xd6q\xd3\x19\x93W\xad\xf4\f߄\xdfUi\x89\x82\xe8\x13}\xea\xf4\xa4\xbe\xf5z\xa2k2\x85\xa2`\xfa\xbc\x90\xee\xff\xd59\x05\x8dd\x02\xe7_\x8b\x11\x0e\xa9\xc27%\x8b\xe0\xa9\f\x82$^\xb7;{\x003\x01\xa2a\x1e2s\xa0\x8fv\xd3#c`G\xb6@\x00\x9b\xc4\\\xbb3\x05\xd6\"\xfeɩ >K`3\xda\xdf'\xe1\x02S\xe16\"\xfd\x89\x10\xab\xec\x80mQ\xfe4\x95\\\x1f>\xc2\xff\f\xd1\xfd\xc3G\xf6wD\xf5\xc9J\x96I0\xb7D\xf4}d>\x916;\xa3\xf9!*\x9f\x06\xb3;\x92ߊȧ\x12S\xaf(~\x8f\xe0TO\xe5:ݓ\x9c\xac)\xf9d㻹\x02=\x97<\x9a\u05f6\xf8\xec\x1b&آ\\X6\xa1-{d\xcb*\x9b9\x9eFB\x9e\x93\xd3:\\\x18\xce\x02f9`\x13K\xcaxJ\xa9:,\xad7\xa7\xe8\x9f\xd0e\x96\x01\xe4VN\xbe\xaeC\xe0\xd10\u007f?\xaeV\xee\xbaj0M^\xc4R\x9ek\xa8\x88\xf6\xdd\xef\u007f\x97\xb4\xfb)\x96ab\xc2\xc6\xd3\xc9\x1a\b9\x1a\x93\xfd\x135\xfa\xa8\x1b\xa9\x8e\x94\xe7I\xceؑ\x98A\xfe\x9e(\x1av$e\x10\x96&f\x0f\x94\x90ыs\xf6L\xc4ؑ\x84\xe1q\x94\xa8\x80l&`\xac'R\xa4\xa1<=\xf9\xa2\x87l{\xae\xa4\x8b\xed\t\x17\xa9$Iz'[\xf4O\xb48`\xb7\xc3:s\xa0ww\xfc^.\xba\x03x\x0e{&U<\x17Z\x0e\x91B\xf0\x11\xbb\xcf&\xefj\x9f䉞\x89\x13}\x92&R\x13&v$K\xf4\xf14\xf7L\x94\xe8E>\xa9\xe1\x88\xe4PD\xff0D\xef\x10Ď\x84\x88>=a;C\x0f\xa9\xfd\v\xc3h\x87\x1d\xd6\xc2\a\x89ja3\xe4p\xd0\xd0\xc1\xc1\xc3\x06\xe9I\f\xbb\x13\x18\x1a\x89\b\xa98\xdcL^蓄Ѓ\xa2S\x99\u007fRP%\x99i3\xc1\f\xa3\xfc5p\xba\xba\x85L\x8a\x13\xa2u\x1bsN}\xe7L\xc8Å\xda\x10\r\x89g\xad\xa8>\x12\x8aq\n\xbbzӾ=\xf9q\xe3\x16䣹\fܕ\xd2C\x10\xc1_\xe5\x03\x91S\x03\x82\x9c0\x11\xe8 ޏZ;\vj\u007fQu\xac\xed__|\x15Ϲ\xdcd>_\xc7\x0e\xba\xb6\xb4~>\xbf\x9e\xff\xc0\xe1\x1d{\x1e\xf0\xb4\x8c\xf7ѷ\x9c{\xceA\xd8\xe6\xefћW\xb7\xe1{\x81\xf3\x0e\xdc\x04\xbdԾlC\x02\xccϔ\xa8\x92\xd3ΞL9#\t\x9d\xc7v\xa5\x9bթc\xd1`\xb7\xa4\x9a\xd5ic\xf1\x13ݖf\x96\x942\xf6\xd1=\x9ckib\xe9\xe6\xe7\x96\x141\xaf\x9e%*\xf1\xc9\xe9a\x83\x1d\x169v\xa4\x81\rv\xd8'd\x87}\x1e\x16F\xa3\xd6\xc97\x8afps053\xb0+\x92\x97\x8az\x91\x11\x14\xbc${\xc32\x19\x01\x90;NU\x15\xae\xc1\x8a+Ӓ'\x14\xaf*\v)\xda՟\\NE\xb3\x88K4P\x9f\xedұj\xaf(\xa5\x9c\xd0BI\xa7\xf6\x11U\na\xa5\xae?K\x16)\xd6V\xd2i\x12\xb2Y\xb3G\xb3\x99\xdd.\xabba\x15\x1c\x96 _\x1e\xe6 \x82\x96\xe9'lg7\x95*c\x13\xbe\"s\xcaS\xc2/\x0f\xcc\xcc\t%\xf7\x8cs?\xcd1\xb9\x05C̜\xe9Dg*\x97b\x86\x9bA݄᱀̪\x1d\x19\a*\xca\"m\xfdVY]\xc9R\x85\xf5\xfb\xb6qa\x96)I\x1b\x82\xf1\xb3\xb0\xd5\xc7z\xf7\x81M@\xacKP,5\x84:M\x0fL\xc3Y\x1f̆6\xa3\xee\x1c\xb8u\x17J.Y\x0e9\x99\xac\xd2\xe8_樵\x8e\xc9{\x84\x17\xf8\xbe\x90b$`F\xadm\x14\u007fR\x9d\x10wg\xde\xcd\xd3գ\x109˨I\xb0\xb14\x16֫\xcb\xe9\x91%\xa3\x88\x85\x06\xe5F\x03=\x11\x92HT\x8aK\xc1\xcc\nc\xa3\xf3Ґ\\>\x88\xd31\xb6\x9eMaR\x94L\xc0P\u007f\xafյ\x12D\x81\xa5\t\b:\xe1)\xca\tf\xe2\xdeu\x12(\x99\x025eBw\xbf\x195\xd0\xe9\x0fp\xf4p\xd8\xe3\xc0\xb4\x8f\x80NI)4Dߟi؇\u007f\xfc\xd7\x0fg\x1f\xb2\x05\xc8\xd2|R\x0e\u00879\xcb\xe6M\u007f\x03[\x80&\xb2\xecsm\xcdH\xf2\xc2O\xab\x9b\"\x9e\xb9}\xe4/Ϋ\x98\xa45Ɔ\xd8;\xe2F\xeb\xd5\xfc\xaa\xc4\xe9\xa8uS\xcb\xc3^_\xdf\xfe\xf4\xdd\xc5_.\xbf\x1b\x93K\x9a͛eH\x05\xa1VnD\xc1D\xb92\xa7K \x94\x94\x82\xfd\xb3t\x9d\xc7\xc9I\xf5\x9dӐ\x83\x1f\x057-_?\xc9R\xb4\x82\"\x8a\t\xb46\xe8;\xa6\xb1\xd1+B\xf1\xe9\xacR\x03\x99*\xb9\x88cJ-\xeb\x91\\Z0\xce[\x84\x96\xe6\x1c\x14\x90\x19[F\nY\v\xd57G\xa6yH*\xc6#lO\x8f\xd5b\xe9D\x96\x91&\xd0\x1c\x88\x00cOw\x15\xe1\x92B\xb7jږ\x1at\\~\xf9\xa4\xc4T\xeaB\xb1\x05U\x8c\xaf\x9a\x93\xb4\xea\xeb\xb5\f~\xb8U\xac\xa8m\xa2\xf0\xf5\xdb\xcb[r\xfd\xf6\x8e\x14\n\xcbz\xba\x9c\xe1h\v\xd2n/\x99\x80\xdd \xb7\xe1\xf9\x98\\\x88\x95\xfb\x90\xe3\xe5\x91Z\x06g\xda\x00Z*ޕ\x10\x9a\xd6\x1f}5\xc6\xff;\xb2;\xa8bCDUzy\xb6q\xc9\xc6y.\xd8$\xf2\x1e).\xbdA\x03=\xef\xd8$\xa4z\xad]\x9a\xf0뺱\xa8WP\xb8\xbe\xec\xb1ҒV$\x8d[\x88\xccО?\x9e\xec\xd3Iw\x80f\xcd%\xc5{\xdd:\x1d^\xd3\xcaa\xe5\xe85\xc1\xdf#Eì\xba\xba\t\xe4\xe84j\x94\x04\t@-\x1dZ\x9d\x84\xe5n\x82.A\xe2\x8c|E\xfeD\x1eɟ\x12 \xfe\xf1\x0f\u007f\xf8\xfd\x1f\xe3\xfdY}\xf4\x89>ʨ\xf3v_\xdd\xf4\xdc\xe7\xef-\x1b\xb3\x90\xec\xce\x18I&,鎋\xb3\xec\r(+&<\xc5\xc4㲇\xc7\xd6.\xe1\x93${\x97\x85q5\xad\x95/g\xf4'@\xac\x9c\xb0[\b?\xc5\x17K\xfe\xe4\t\xdfN\xf1\xafR\x9bk\xcfΘn\xcc8\x89\"\xfc\xe1&\vj\xb2y\x9b\xdfZ\x13\"\xe9\xd8\xd7\xe5\x97I.1\x96\xe5\xae\x03\xcdYB\xbe\xf0\xc7;\xbai\xe9\xb3-Jݤ\xa8>\xactͭ\x8f~\n\xaf\x97\xbb\x82\xe5\x89<\xa1\x90\xb97\x18\xec\x92\U000c640c\xb5\x18\xdc\xd8b7\xf8(EZ\xf1\x97\xfab\xbe\xe5\x85\x19\x15\xee&\xf1\x14\x94\u009bf)(]a\xc6$\xcb \x81,{p\xc1BI#3\xc9Sh\v\xb5Ɨ\xe4\xeeU|\x19\xc5v機\x03\xfah]\xb4\xfaM2a\xfe\xed\xf5͙\x9d\xd2\x19\x91\x8aܾ\xba\xbb\xe9w\x95\x89\x90\xa3\xbbW7G\x1fpOҢS\xa3\xb6.\x17\xf9n\xa0\x828\xeb\xacOE\x81\xd8D\xe7V\b\xd0Z0\xa3\x05-F\xf7\xb0\x8a\xd2yӱ\x94\x84\xa3\xcdI\xbb\xc5/\xe8\xfe7\xc1\x14М}B\xc5\x14<\x97\xaa\xe7\xd5]Ua!\x97\x91N#\xb4\xf6\x02t\x10y!\x990\xba\xab\xd4B\x14\xd8M\x93\xf1\x93IY\x1cJ-t\x8c\xa1\xd4\xc2\xd61\x94Z\x18J-\f\xa5\x16\x86R\v\xddc(\xb50\x94Z\xf8\xac\x92\xa7\x87R\v\x8d1\x94ZH\x18C\xa9\x85mc(\xb5\xb0\xd7\x18J-l\x8e\xa1\xd4B\xe7\x18J-t\x8c\xa1\xd4¾c(\xb5P\x8d_\xce\x15\x9f\xa1\xd4§z\xc5g(\xb5\xb0\xcf\xf8<.B\r\xa5\x16\x86R\v\x01/C\xa9\x85\xa81\x94ZX\x1bC\xa9\x85ϕ\xa8\x86R\vC\xa9\x85\xa1\xd4B\xf7w\u007f\xedv\xd8Pj\xe1S\xb5\xc3>\x0f\vc(\xb50\x94Z\x18J-\f\xa5\x16\x86R\vC\xa9\x85\xa1\xd4\xc2Pja(\xb5\xf0+\xf2*&i\x8d\n\xb4,U\x16g\a\xb7\x89\xec\x95\\\x14\xa5\x01\xf2.\x80\xaa\x94娅\xa3,a\xbay\xa3\xff\xc3v\"̤\x98\xb2\x99W\xf4\xce\x17T\xd0\x19\x8c*\xfc\x8c\xea\xfbw\xe7\x1f\"7\x9e\xb3\x05\x8b+\xb2`G]\xb1ই\x87#Ѡ\xeekN\xf74\xa6\vj\f(\xf1\x92\xfc\xc7\xc9?~\xfb\xf3\xe8\xf4\xcf''?|5\xfa\xf7\x1f\u007f{\xf2\x8f1\xfeǿ\x9c\xfe\xf9\xf4\xe7\xf0\x8fߞ\x9e\x9e\x9c\xfc\xf0\xed\x9bo\xeen.\u007fd\xa7?\xff \xcaŽ\xfb\xd7\xcf'?\xc0\xe5\x8f{\x029=\xfd\xf3\x97\xd1S=\xb0q\xda>\x8f\xdf!\xe5\xd4)Eȷ\x17\xf4\xd12\xd8xRX\xc8R\x18w\xcb\xc6\x1d\xf3\xeaD\xb84\xac\xd8CI>\x95\x83I\xfa\x18\xda>\x1fm8\x9f\x11c8\x9f\xee|\xbe\xf3\xb4\xd3>\xa1\xd1s\\x\x95i\xc7\t\x8d\x86\x19\x047\x1a\xba\xd5<\x99&r\xc1\x8c5\xa7S\xae\x197\n\xa9\xe0\x95\x94\xa6\x8b\xda\xf1\xaax-o\xeanS0ݼ\xa0Ѹ\x14.\x83훢\x96RQ\xc7)\x90\xe7\x8cr\x982\x01\xb9SO\u007f}\xfc.\xe95\rY\xa9\x98Y\xbd\x92\xc2\xc0c\x94c\xbf}^nۀ\x88ی\xf8C\x13&Dd\xe1\xae\x1d\xadU\bÛ\u007fq*+\x10U\n\xf4g\xb9:\x17`\x9cs\a\xcdp\xbcٳ6\xf9(\xf0\xc1\xf5\xe2\xa8)\xb6\xe4\xaeO)\xd7ь<]\x1a[E\xe6\x8d5\xdf{\xedb\x05\x85\xe4 \xa4\xf1\x1e\xbf\xa4\xd3 \xa7\b\x8d8\x9fB\xe3\xb2@K\xe2%)\x99\xb50f:\xe0\xfc\xa6\x9a9F\x98\xe2S>4\xac\x9bq^\x18W^\x86\xa4\xa0\xbf\x02\x9acM\x99\x82\x9a\xb9\xcbS]P}\x0f\xb9\xfb!QǮB\xb2v\xc6\xd5\xd2\xefV\x05$\xc7SQ\xb7vٿ\x18\xe7\x8d\xf7\xc6\xf6(\xefE\U000f70af\xdeIi\xbe\xaeʘ\xf4\"\xe4オԎ\x03E#e\x8ee\xbb\xed\xfcF\xb8\x89X\xb6\xa5Yi\xc5S_\x8a\x95\xf0\x81\x19\x84*Ņ\xfeF\xc92Z\x15\xd8Pֿ\xb9z\x8d\xfc\xb2\xf4\x192¨\x15\x96\xa6Ja\x12\xed3W\xd9c\u007f\xf39MI\xd96\x15{\b\xe1z\xf2\x86\xae\b\xe5Zz\xc31!\x18\xdc\xe5!!\xdeU\x93r3z\"\xcd|ݧ\x83\xeca\xf3;\xf1\x05\x8c\xea\x04\x9bʓi\x97\xd0Dž\x84`\xe9=hR(\xc8 \a\x91ES\xef\xc7I\x83@ʿ\x96²\x97^\xb4\u007f\x15\xf2\u007f\x9c˸\x9fU\x8f\x99Jަ\xa7\x98\xaf\x84̥Ԡ\\r\x98*!m\xe3\xbf-'\xc0\xc18G\t\x16\xb9\xa5\xc6y\xfe\u0602\xce\xe2O\x135\x95(4\x92\x80Х\x02\xef47$\x97\tf\x80\xaf#e\x97\xfe\xb7\xab\xd7\xe4+rb\xd7~\x8a\xe4?\xa5\x8c\xa7T}\xc1\xdb\x1fk܄M\xc3\x14-J\xe3u\x02\x81ƾr\xac\xfa\x8c\bIt\x99\xcd\x03NS\xbcC\xc1y\xe5oH\xe1\x15\xb6\x815}\x02\xac\xa9\xa7`\xfd\x9b\x06\xd5[\xae\xfe\xed\x03\xc8\xd5>n0˛ڻ\x86\f\x85,\xc0М\x1a\x9a\x12|+E\xa3:\xe2\xdaQH\xa1\xdd\xddG\x01I;\x1a\xe6\xaf\xec(|\x1c)\xad\xe1;&\xcaGw;\xa0\xbfC\xf9\xf6\x12\xc1\x11\x1fJJ\x91(\x13 \xb4(8s\xe5\xfb\xd6Z\xc4\\\xb5H7m\xef7MM\x14\x0f\x94siՌ\x84\xf0\xb8\xa2\"\x97\x8b\x8d\xc5[C\x14h\x82U\xdcXp\xc7\xe1\xdcv\xd8\xe2ew}8\u007fm\x87\xad\x8f\xeb\x9e\xc3\x12\x12\xaa\x94\xaf7Q\xb2P\xacA\x1a\xa8\x06\xc1&y?9\x9d\x00w\xaa\xa1;9z\xf3\xe4${E\x13\x9d\xaaJ\xf2\xfe%/\xdeI\x0e.7> ɂ\xfd\xc5\xe0\b_\xee\x8b#\xf4>\xb5p\x94\xecE\xff\x14qT&hxd\x1dGVMl\xe3Ȃ\xfd\x85\xe0(9\x04\xa1!\xcb䢸Qr\xca\xe2\x0f\xeb\x86\xe8\xf7\xe0\xea\xe4\x9cx\xd1_j\xe8\xca\"G=\x12\x81\xc7k\xe4~2T5.=Q\xe3d\x9e\xbf\xc5\x15\r\xf4\xffk\xa8\x10ȵ\xcf\xd6\xf4\n\xff\xd5\xf8\xd96\xf3\x85\n\x99\a@\x1fT\xbaɌr\xecH\x94F\x17d\x9d6\xd6\x01\xf6\xb8\xcfE\\c;\x0f'\xe4\xf4aK\x16\xfc%\xc13@Bs?\x99C\xa3v\xbc\xbb\x80w\xe7\xee\xcbX\xd8I\x80õ8\xab\xa7\x84\xe4\xab<Į\xec\x17Ӧ+}\xa9\xec7UO%\x8bp\x10yj%\xa8\x82\x9a\xf9\x19Q\xc0\xf1\xe2^`h\xf7Ρu\x9c\xb6O\x8d\x05\a\xce\x106\x0e\xf5l&E\xda%v\\5\x86\x05\x82F\x947\xe5{\a.\x98Ιew\x86\x89YB\nF\xedQ\xa1\x9c\xb72\xf4\x0e\xe1R\t\x9c\xa0ꓺ\xe9:H\xf6\xd9;bn\xfb\x12{\xfb\x0f\xb6\xb87jwE\xbc3e\x87{ù+\xa2A~\x1c\xf7\xc6l\xa1\xe9+e\xbfk\x18\xe5\xb7E|\x87\x1f\xb2N\xcb\u07fc\xb9\xbdh\x83L\xe3\xec\x98\u05eb\x9czla\x12\x9a/\x98\xd6L\n\xf2\x00\x93\xb9\x94\xf7IpOB\xea\xfc\x8c\x99y9\x19gr\xd1Ȣ\x1fi6\xd3\xe7\xfed\x8f,vҚ\x9c0\xc1í\a\xe7!\x14F\x87\x88\x81]L\x9a\x96Ua\x15\t\xd0w*\xf4\t\xae\x9bh\xbfN-R\x857\x16>\xb8J\xb5I\x8a\u05c9\x05ş \xc7d\xbc\xf8\xea2\x8djO\x8e0\xeb}I\x13\xb7v/]\xe8\xe7÷\x11p\xa6Z\x06\xba\u007f\x1b\x81\xbfְH\x0e\xae8D\xa2\xddǦ\xad\x86\u07b5B\xe2\"ډ\xb6\xe41\xd6n\xf3S\xe5\xa2\x1f\x91\x1a\xb0o?\x8f%ی\f\xf16\x92\xb3\xe9\x14\xc2\r\xe7H\xb1WPE\x17\xd6p\xd0ħ\xfeN`\xc6\xdc5\xd3J\xb5\x8a\x8cPTE\xc2Μ\xba\xc7\fY\xb0\xd9\xdcyi\b\xc5R\x94\xf1\xe5&\x8d$\\Ҝ \x17\x97\x8a=4\x9f\xde{\fͧ\x87\xe6\xd3C\xf3\xe9\xd814\x9f\x1e\x9aO\xef=\x86\xe6\xd3C\xf3\xe9\xa1\xf9\xb4\x1bC\xf3\xe9\x8414\x9f\xde6\x86\xe6\xd3{\x8d\xa1\xf9\xf4\xe6\x18\x9aOw\x8e\xa1\xf9t\xc7\x18\x9aO\xef;\x86\xe6\xd3\xd5\xf8\xe54=\x1b\x9aO\u007f\xaaMφ\xe6\xd3\xfb\x8cϣ5\xdc\xd0|zh>\x1d\xf024\x9f\x8e\x1aC\xf3\xe9\xb514\x9f\xfe\\\x89jh>=4\x9f\x1e\x9aOw\u007f\xf7\xd7n\x87\rͧ?U;\xec\xf3\xb00\x86\xe6\xd3C\xf3\xe9\xa1\xf9\xf4\xd0|zh>=4\x9f\x1e\x9aO\x0fͧ\x87\xe6ӿ\"\xafb\xe2M\x91\x9cE\xb5lۣ[@J\xed\x93P\xbb\xd32\xb2r:\x05\x85\xc2\x17g\x17\x94\xa3\xb4K`\xa13T%\xba}F,6\nT@sW\xf3\"\xce/\xd89\xadP\x84\x14ۗ\xb9{\xa9\x91\xe1\x01r\xf9\xf6\xeb\xda\xe9\x9a\xd2\xea \xedv \xae\xe7\xad\xc8\xd2\xef\nՄ\xd0Q\x9d5\x0e\xb7.\x01?\xe3R\xfb{\xb2\x88\xeclN\x85\x00\xee\x95n\x16\x87\xd99\xd5d\x02 \x88,@8\xb5\x85\x12\xcdČ\x03\xa1\xc6\xd0l>\xb6+\x88\xf3\x9ey\"\xf0]\xeb\xea\x99j\xa3\x80.\x1c1(X\xc4\xf6\x19\xb4S$4SRk\xb2(\xb9aE5I\xa2\x01KeD&-]M\xeb\r\xc6$\xf1\xfa\x02\xeaY\xb5\x8a\xe89\xba2h\x8d3o\xa82g\xd8\x0evQ\x98\x95\xbbK\x15'\xf8\xb0k\xa7҆d\x9c\x810~ծ>#\xce\xf3\x8c\xc4\xe6\xc6\xe3\xf5]\xb7\vڣV\xe4\xe8\x15)\x8cv7}\xd2&꧘3\xed\xbdo\xfa\x8cP\x13\x04e4\xd1\aZB\xb2\x0f\n\x9c\x9b\xb5\xff)q\x9auI\u007f]_5\xab\x99\xe1\x94\xd38\xc500\xa5\xb3V-\x87\xda>\xc4$wd\xabQ`\xb1\xec\x90\xc3\x02\x1e\x1c\x01K\xcb? \x03\xb6D\u007f\x90\xe5\x8cQ\x10\u05f9\xe8\xb33ц\xee\xfa\x06\xb4\xa63\xb8\x89L\xb1\xd9\xe6 \xc6,\x9b\x9a\xb8\"\r.\xacFfdC\x87\xab/\xa0\xb4-\xd0(\xb0\v\xb7\xc6\xca\xe6|P\xcc\x18@\"\xc6\xceU\x98y\x18\x99\a\xbe1\xb9\xe6\xf5\x987\xe1\x83\xeeC\xb1Tk\xf5)\x91\xbbK\x1d\x13 \x13\xc5`J\xa6LP\xee\xefa\xc4]8\xc2~\x16T[ҤZ\x83B\x9f\x8bw;\x05\xdc\xc4\x11\xec\xf7\x1e\x91F\x95\"\xa3\x8d.\x97X\xfd\x8eM\xc9\f\xefzD\x1a\x13s*ȿ~\xf5\xef\u007f$\x93\x95Ղ\xd186\xd2P^m \a1\x8b\xac\xed\xef\xc5S\xbb\x0eYE\t\x9c-X\xac[\xc8\x1a\x03\xbf\xbb\x9f\xb4\x03\x8d\xe79,\xcf\x1b\xf49\xe2r\x16\x87\xd3W\xe1~eug2F\x91Or\xedw\xb0\x01\xc9Y\xb6Jf\x04\xa1y\x0e\x99\xcb\a\xe7\xca\xebyb\xeb+\x8e\x85,J\xeeR2\xbe\x0e\x95%\xa3@\x96\x1a6\xabau\xf2\xc1Xj\bS[\xef\x10\xee\xaeL\xf9\xa5\xc4)-\xbe\xf0\x9c\x0f\x8dW=s\xd0O\xfc5\xe5|B\xb3\xfb;\xf9\x9d\x9c\xe9\xb7\xe2R\xa9\xc86\xfbH\xfd\x01\x1f\x9cZ-f^\x8a{ly[\xd7\x1a\x96q\xd2V\x96\xa6(M\xb8\xe4\xddt\xef\x86͌\xae\aY)h\xc13\\\xcf\x0e\x1e\xed\xb9E\xf7l\x1c;\xf0\xc5w\x1cw\xe1rV\xcd[\af\x10{#\xe8w_\xfd\xeb\xbf9\x96E\xa4\"\xff\xf6\x15^\x19\xd5gN\x88\xa1n`\x15\xd9\x05\xe5<6\x98\xd5d0\x96\xe8\xc7\x1dL\xe2\xd9y\x84Ig\a\xcfbr\xdf\xdd\xfd\x1d\xedmf4\xf0陫=\x12<\x88Q@\x8fQ\x89;\xf6R\x16\x8b\xdc|\x04\x83v)y\xb9\x80װdY\\\x84\xbf\x85\xea\x16\x94\x10\t\xe2L\x1b\"\xe3\xaa@L\xb8\xcc\xeeI\xee\x015\xeef\xac\xf7\xb1\x8e\xc1L\xc2-\x94\xad\xab\xab\uf7d0\xd8fD\vZ\x14U-\aE\x1fZ\x8bE^\x12}\x01\x85\xa6\x06\xaaӳ:\xdctc\x15\xf6\xf0n\x03\xab5\xa0@0E\xac\xf4s\xc3\u07fc\xdehH\x15:\xe8%\xe5\x1a\xf8=qz\x9a\xdd9\xe4\xcc\xf1\xe1\xf5\x1eI\x0fiwzZ8\x16U\xae\xc0\x82\x1ao\xd3$\xe6\xcf \xd5\x16\xa04\xd3V\x81y\x8fg\xe2\x15\xa7l\x91~\xc3?\xa5!A\x8f\x16\xb0)y\t\xa3\x06\x9dF\xbe\x18\x8d\xe8^u\x8f\xe2\xee\xb68\x96\x86-}ӹ\xfe\x8d\xcc= dծ\r\xb35e\xa3\xc9a[\xa1\x87^\nG_\xb6\xff\xbe\xc6Q\x93\xeb\xbbu\xc6\x1fg<@\x0e\xa6g\xf6\x1f\x83}\xe3\xe4\x0f\xc0\xbd\x91o\xfbe\xf4\xad;\xd7t\xd8x\x82j\x98^\xdeG2v\xb9\xb1\t\xe0-\x05\xf9\xe9\x91\xe3\x97\xc7\x1f\x94\x87;t+Y\xd0\x19Z#=\xb1\xbe\x0e\xae_\xa1Yk&#Īg\f\u0085\xbc\xaam\x9e\x04\xd4]\xa8\xaf\xe5p0\x9f\xb0\xf2X\x02\xc4\a\xba\"T\xc9R\xe4.\xf6P\a\xa5ެ\xa1\xe3Z\x8a\x94)\xfb路4Uմ\xc54\x01&ȋ\xf1\x8b\xaf>7\xc1\x8f+Y\x13\xfc\x89\x85\x9f\x1b|\xeb\x83b!\xb4l\uf2497\xde\xc5ZwXO*;\xe9b@\b\xe4A1\xe3\xa9\xf9\x81i '\xb1^\xf30\xa4jֲ\x0e\xfc{\xd8\xe9\xfbj\xa1\xe3\x1eVU\xd8\x1d\xf1b\u007f\b\x01\xd0\x1a\x15\xbe\x8d\xfbnٿ3ʹ\x97\xbe\x11\xb0\xb6\xf7\xf4+4+\xb0\xc4\xe7HŮ\xe1X\xfbV\xcdR\xe89+\x9eJ\x8e\xa1\x98\xb2-\xa7\x01\xfbU\xf3^\a\xde\xd1ߕ8#\xd7\xd2\xd8\xff\xb9|d\xfa\x89\v9v/_K\xd0\xd7\xd2\xe0ӽ\x91㦶7j\xdc\xe3H\xd2\xc2\xf1H\xbc\xa4\x84ߨ\x96y\xf5\xf4\xfd\xf7\n\xc5L\x93+a\x19\x95\xc7AuYQ{\xf0\xcd;\x86\xc8\xd5vk\xa2\xee\xdb-\xf8\x0e\xad\xf6\x1bM\xcc5?\xb5\x1b\xe5\xadi\xb8)8\x8f\xb6\xfb\v&h\x17\x9cf\x90\xfb>\x13v㍢\x06flw\xfb\x81\x05\xa8\x19&\x1ad\xf3]\xab\xda#t\xb8\xa7\xe2}\b\x15y;\xab\x19Uh\u007f\x0e\x15\xda\xcb\x10\x14\x9f[\xb0\x11:\x89Q~\xf3$G{\x12c\x9b\xb2\xc8}\xda\vsZX\xca\xff\x1f˞\x91\x88\xfe\x97\x14\x94)=&\x17\xfe\x86ʖ\xef6\xdf\xf0\xbaN\x13\xb8\x85\xcb4\xb1\xbb\xb0\xa4\x1c\\\xa1b*\b\xec,\xbf\"\xa7\x1b\xd2\xf2\x8c<̥F\xc9P\a\x91\x8e\xeeaut\xd6:![ ڇ\xaf\xc4\xd1Y\x15/k\x1d\xcaJNa\b\xe3\b\xffv4\xde\x10\xb0[`?!vwRɎ?VZ\xf7\x1b\x97ڴ\xb9\xf3\xfb\xd2\xc7N\xdaب\xc0\xd8\xfcf\x8b8\x9a\xcaqˬ\xe8\xfa$U30]&\x88ט1\x95aL.\xc4j\x03.^\x8c\xebT\xb9\xbd\x11W\xd1Y\xd1j_\x84--1C\xa2\x01\xca'.\xe9nC\xd8>\xb8\xb9k;6\x05\x05\xa8Zµ\xcc\xe1F\xaa\xae\xfc\x8ev\xbcf\xfd\xf9\x0e\x8b\xb6\x81\x14\xc9s̳\xc7G;拺\xb1\u05cb\x0fi|\xfa\xef\u07fc\u007fj=\xef\xaa\aw/\x84bo\r\xb7_\x1d\xeb\xb0ﻻ6\x82\x16z.\r9\t\x97\xda3.\xcb\xdc\xdf\xecW\x1d\xf1\x9e\x1e\xab\xd4\xd9\x1c\xf2\x92Cw\xd3\xc1\x8d2\x95\xe1Ѡ\xfb\x95\x82\xfd\xb3l\xb7\xe8\r\x1e*\xfft\xd7A\xa8qR\x99\xd6\r\x8f\xaaeG\u007f\xc1\xfd\f_\xf2V\xa4\x87\xbc%\x15\xbe\tҝ\x05\xa9\r\xdeS\x12\xa6Qt-\x98\x9d\x99o\xcf\xe1\x1f\xef\xbcf\x17ְ\xed8t\xb0\x8fn\xe1:\xf2_݈\x88o9V.\x97\xbe\r\xa3\x8b\xe6n]\xce}F\vS\xaa\xd0\xfe\xbaT\xd8\x0f\xacnaB\x03\xe6<\x8aZ`\xb7\x1b\x06\xde/Ȥ\xb8c\vІ.\x8a'(\xe4\xd5\xe6\x1bv\x03\xa4\xcauU\xe9\xa4\xe9\"\xa8\x9bnuYŴn\xf5\x96\x8f\x1b\xb0\x1d\x18\xd4\xc9,h\xc8\t,A\x10\u007f\xc9\a#\xef\xce\x01\xd1\x01\xf4\x0e\x8d\x13\xb5\xc4X@\x80\x83\xf9\xbeS\xa9\bvի\xa6\xbeI\x11\xe1\xeaxN\r\x8c:o\x12\xeeu\x12;\xa5\x8e\xeb\x91\xfb\x04\x82/]#]\x94@\x19\xe6\x89\xd9\xed\xe5ܽ\x1dn\x1e\xf8\xab~\x0f\xa0\x80\xcc@X\x14wr\x1c\xafʺVO\x16\xb1\xfe\x04W\x0e\x9c;\xd7\x1d\xab\xa4<\xb4\xf0\xc5\n8A\xaalu\x99\xe1#\x9d\xb7\xacv]\xa0\xf77>\xde\x01\xd5]yK-D|\xdd|\xd6\xdb*\x0e\a\xb8\xf4\x8c\xba>y\xaec)S\xd0I\xfa~J\x12\xbf\x1cq\xc6\t)\xe6T?\xc5.o\xec3UK\xaeơ\xac8\xe5\xbb-s\x02Q.6\x81\x8f\xc85\xb4\xf0[\xce\xf1\xa1ƥ\xb9 v\xfdR\xf4\x81+\xcdZCȅu\xe0d\x81 \xea\x01\xe1YX\xe6a\xab\r\xb8L\xdayL\x88H\x8f[\xcf·a\xb5g(\x15\x0ekv\xc6dy\xa0\xfc=\x9a\xef\x1eq\x9c\x98\xffy\xf7֫h\x92a!\xaeꖺD\xf5\xee\xd3\xedß\xefz\xd50Ѓz\x96 -\bx\xe0\xf5\x03\xa6^\xe9\xe02\xe1\xc0 I\r\x95\xa3\x16\xa5\xc1U@&mH\x02h\x03%\x1a\xa9S\x99\x04D\xb9\xb3\xcdt\x95\xa7\xb0A\x02w\xddt(\x8d.\xd18\x19V\xa8/\x1d\x8bԩ\x1dp\xfc\x86&\xe5[y-BˊS\xaf;Lk\x1c\xbcnK\xdb\xf2\xcf\x00\xf7\b\x035\x12\n\xf4\xe6gL\xdc\x1a\xee\xd0\x10\x99\xc0u\xa2\xd5\x0e\r!\x90\xe8G%\xff\xd3ж\xa4\xb1\x8e\x15\xc9am6\xda\xc2\xeb\\\x89\x1cv\"\xaf\xf0\x02\x84J\xa1\x10{0H\xa3@\xa5:\xf4\xb8\x89]\xc3ߵA\x90j\xab\xaf s\xae\xb4W\x97\x97\x8f\xd2\x05K\x9c袨\x94t\xfbK6\xaarS9m\xece\x8a;\xcc/\xad|\\\t\x93d\xd2a\xe2*\x83\x97\xa2\x94+f]\xb15^\x17\xe9\x1f\x82D\xed\x9b\x1e\xaf\ak\xc5\x17\xb6\x97G$@\x86\xd3+\x8c\xef\xeag\xd1\x02MU\x84\xce盻\xfb\xae2I;D\x9fq\xefhX+\x02\x02L\xaa-֫qkt\xc14Q\xa5\xa5\x96\xca\xf1\x1fI.Q\r\xe1\xb7զ\x90\x8e\xe4\xfe\xef\n\xad#Y\xadᚷ'\xd2ê\xa4Փ\xae\xe1V\xc1\xb5(0\xbf\x16\x16\xbf\xb9\x00\bi\xbb\"`\xe3D\xd0\xddY\x87\x8d=j\x9d\x1f\xc2.8!\xaf\xb0\xc6\xefJLzK\x86\xfaɭLxa\xb0\xe5kL\xc0\xc0\xfa\xf92\xbej\xa16=\xd4|X\u007f\xd4\xda\xc4\xee\t\a4\xa161\xeb\x83_&\xd0䟰(i\xb9ΰx_7#\x16\t\xa3\xb4\xf1v\xc2f\x19̛\xae\xad\x1a\x1c\x18\x15\x1e.C\xc2k'\xd3\xdaj\x1c\xa0y\x1cQ\xcf\xd8VT\xb9{ \x97\x01\xed\xbd\xfe\x8c\xd6\xc9d\xac\xe5`\x12\xefG;\x06y\xa3%\x84]\x86\x86\x16'\xff\xc0\xf6n\x94.\U0001ac58\xb2\xc9\x13O\xb4en<\x02d;\xf3\x1cJ\x9d\xc2Ώ\x04\x9b}`\xfaP6\xad|6Z\xe7(\xc6P\xc3/I^\xa5\x986\x1e\xd5(.\x83\xd9\xde\x1ctb\xdfSHEZF\x9e\x1e\xb1\xaa\x9a_'\xe6\xc9\xfb\x950\bd(\xa4\xf24Az\xb7d3\xa1pT\xa4\xc3b\x82ϣ\x1a\xe9\v\xf9\xb8b\x93\xe3\x158S\x8d\xe9z\xa0!\x8c\x11\xfb#\x98\x05\xff|\tdM\x9fڜ\xe72a\x0f\xb41ڌ\x1aC31\xbf\xffC\xc02\xad\x9fb@\xfa\x1b\xb5k7'H\xf8\x18\x04\x1b\xcc\xc4Njc\x87\x1e\x0e~\xc1\xa4r8\xb5\x8e\x84\x83Tn\xb7h\x88\x16;ԍ\xff}\f\xac\xe3&\x82\x8a9.\xf8\x83y\xb5B'\xe11\x1aSSaSt{^\x80\xdc6\x02K/`+s\x87\xecK\xcd1\xdaqtf%\xf7\x92\x00\xc5\xee\xbdT\n\xe1\x92\xec\xa69\xd2F\xf4\x18`5$\xe0\xfd\xf2p\x86a\x19D\x90\x84Ʃ\xe0(\x884X\xf8\xe8\xca=\xaf\x8f\xb6\x86=\xc0w\x1f\xdfc:\a\x19\xc4k\xea\xc1\xa4\xde\r<\x9d.\v<\xc1(\x92\x9dI\xb1\x9b֜\xf1|\f\xed\x02\x04<\xe1\xde{V\xa3\x87˱B\xa2\x15\rI\x83\x1c\xd0c3\xf2\x84{&UG\xe8\xa2\xe8-Q\x15_\x9ep\x1f\xdbt\x00*\xf1W\xc7(<\xbaT\xc1\xb3\x88YJmi@\xad\xd7\x0e8\x1d7YXf\x94B\t\x88\x9f8\xedF`\xbd\xb0\xf4\x13\xee\xdfX/>Z5\x99,\x17 @\x06\x1b,\xf2\n\v\xf1\xd8\a\x91˴\x19\x8c\xd7\xc9\x02\x8a\xb7\xea\x02>jG\xff\xdc|\x91\x96XT)\xbc\xd7h?j\xc75\xdf\x14b?\x89\x13\x01\xf6\x9dyY*\xbf-\x10.\x8b\xc6oy\xe0-\x94T\xb4\x11\x9b\xb4p\xab\xe8|\xe6\xf1Y\"\xa6\f\x03s\x9e\xad\xa2\xb2\x1c\xd1UZ\xadx\x9b\x0e\xa3- \xda\xe5\xab\x16\x956=I],\xa48\xcab\xcd\xde=\xedV\xfe\x97\x83X\xf8\xb1b\xb0\xccE\x82)\xa4\x15\xc7\xdb9\xf0.\x1c>\xca\x04\n4\x8f\b%\xed\x1b\xf1J\xb5\xc0\x92\xfbr\x82\x16ƻ\x16\xa1\xd4\xdbB\x1a\xc7؊V}d\xcb \xe6\xa8\xe6\x13Q\xf6\xe3\xcd\xe3f\xc9\xdb;\xfbCQ\xe8wo\x8f\x97\xed,\v\xe5u\xe8\x83x&\xbd\xfbQ\b\x0e\xf6\xfeB\xdb+\xab\xf7\xafq\xbb\xa1\x90Ʈ\xe1\x1dߝ\xe7\xd8\xed\x1f\xa2\x84\x9d\xa1\xa2H\x12'\xd2\x02\xe9\xc9N\xe4\xe4>\x90\xf1V\x80\xb9w&\xf4\xf6\xc0\x83\x8a31ϙ\xb6~\xcf\xdfJ\xcc\xf9v\xeb\xfc\t\xf7\xe7\x17\a\xd6\xeb\xfcV\x9d\xc7\xd1$\x9b\u007f`\xb4\x1a\xafE\xab|\x0f\xe7\xfc\xdb9;fK\x96\xc8\t\xce\xdb\x02\xad\x8en\xca\xd7\xcfK\x8e\x02\x9c\xe1 \xdb\xe3usIK.\xfc\xdc,\xa2u\xba\xd4\xd6-b듶\xce\a\x00{\xee\xf6H\x840\xe6\xf4WG\rAl\x1d\x1a\xb0N\x9bp!Jfw\x10 '\xc9\xdbyٓ\xa8\x9bh\xa4'L\x87\xcc\xf3\xd6Bx\x9b~\xeeoJ\xe9\xff\xf34\x13v\x96\x98vit\x82\xd6ΫR\xe4\xce1\x13\xb0m\x82\xb5\xc2\x1f\u07b6Q\xa69&\x94\x1c\xca2W\x9c\xa0=\xe1`s\xf3\xa5\x13w&3D\u007fǨ\xf2)<\x02\xe7T\x15\x85\x18^\xceG\xb3{\xed{\x87\x05X\x13\xf3\a&\xf3X\xb1QY\xe67\xd7*\xf9[s<\n\xa9ny x\xfb͜\x15\b\xa6\x1cO=\xca\\\x87\xfe\xad@\x9a\x8a\xd8\xf3+\x84\xabf\xcdw5\x06{\x92=\xbcɈ\x97\x14\x903\xad\xb4\xeb\x06k\xea\x91\xdeX\xd8Jc]\xcb\xf0\x02\xaa\xd2\xf2u\xf2\xb7=c\xaa\x1bcN>b\xfe\xe4{w\u008a\x99~\xae\x13#\x96\x1c\xac\x03\xf8\x99\xd8!\xc8-H\a\xa8\x12])\x0ex\x91\xb9\xa0a\x16P\xf4B\xf4\x9bI\xe4\x9e\xd9鬪\"\x1e\x90\x15k\xa7T\xb3ѱn\x97\x1f\x84\x8c\x8bN\xc1ibu\xb2@]\xcdn\xedm\xe9gv\xf8\u07bd\f\x98B|\x91EU\x80(H,K\u038d[\x9f?\x18\xd2e\xbc\xac\x9f\x85tu\x06\xa1\xbfX]fM\x13]\x949:\x84\rn\xb5a{`e\x8a\x8d\xfbP\xcb\u007f4\xdfd\xaa\b\xd8\n\x99Wf\x81\x8d^,\x99\xa5\xe7\xb6\xda<\xbd\xfca,\x9e\x91\x15\x83\x19\x19t_\xe04\xcf\xef\x1f\xa5Y\xe62\u007f2\xf8\xf2\xaeii$i\xa9\x9e\xf3Ngi\xb2\xf7\xda\xf7Nk\xe5\x15j?\xe5\x9e\xceReN^\xddӦ\xbc\xba\xa7\xaf\xee\xe9\xab{:(\xaf\xee\xe9\xab{\xfaꞎ\x97W\xf7\xb4S^\xdd\xd3\xe8\xfd#\x86\xc3\x15t><;\x99\xab\xc8\x14\x8c9\xb6gƪ3\x8d\xae\xf3\xca:4K2\xa4o\xc7{\x8e\xe4\xd0'\xbeɊ?\x06\x9cҚ6u\xa5\xdd\xf4\x9a\x94iZ\x92a1\xf9o1\"\xbc\xf0\xe84\xe8\xe9l\xfb\xd8\x04\xba\xb9\xb4\xb9~\xeex\x93\xae\xe6\xff7\x01\x88\xd3a\xf8Zz\xfe\x1b\x9fn\xceU?\xf7\x8d\xcf\x01\x81\xe3\xdfd^ydZ\xdbL2\xdb\xf1D\xfc\xa9\x1d>`9\xb8\\\xe8\x83iz\x89߿i,#\xb2ͦs\xcc\xea[Ktb\xf7v\xdd\xff\xc5\xe9:\xe3lbf\xcf\xd2e\xfe\xfb#:\xba\xaa\xc7nZ{\xd0\xd3\xfaۿ!\xc6\x13\x14\xb5\x01%s/\x80@\xa1\a?\xfcT\xfa#\xf2\xc9\xeb|\xfe\xa0\x16\x9f\x97\xb64\x1b\xad\xc9\x1f\x9a\xdfU\xbe\"\am\xd9\a\x02\xb3\xf9f1LCL\x96\xd9x\xfe\xd8\f\xd5%\xb9e\xb1g\xf0\x88<\xb2\xf8\xec\xb18x\x80\xbf؍\xcd\x19\x8b\xf6\xdab\xf3þMVXd.X'\xc3k\x96\xe4\x89\x19`р\xc5e{E\xe7xu2\xb7\xe6\xd1:\x92\xd95\x9e\xaf5Kr,\x9f+&K+\x8a\xd7\xe8ܬ&\xe3j>\x92\xf8U\x19Y/\x9f\xfb\xfd\x92~\xfe\xf1\xfc\xaa\xa8\xac\xaa\xa8\xb3\xc0<\xcfQySK\xb3\xa5\xa2P]\x9a\x19\xd5d=\x1d\x198*\x1f\xea0\xd7\xe9\xd8Tf\xb3\xa0\xa63\x9c\x8e\x91\x1d\xcb}\x8a\xc8k:B\xb2\x9b\xf1\xb4\xd8\r\x98զ\x99\x06\xe3_Շ2\xbf\xd7\xe6\xff\v\r\xfc\xdaIk\x93\xa2\x99=\x95,a}\x96\xed~\xbcr0\xfe\xe0s\x9d\xf019\xb5\xea\x9ex\xa6\xbc(\xdd|>\x92\xc0\x8fR\xa5^\x93h\xb1t|\x1a~\xa1\x82\x13\xcc\x1a7k:\xe3\xb6\xf5h\a\xa7-\x8b\xa5 \xa3\x9e\xc2f\xef\xa3Bv\r7\"ɚ\x86\x13\x14y\xe4LX:\xd9\x17\xc2\xc1ys\x8c\xbd\f=\xa9\xe6|\r\xf0\x83n\"\b\x9d\xcfC'\xe8ZY\x94\xf9\x1e*\x8bp\xde'\xf4u\xa7\xb0IݱJ\x946\xd3\xe1%\x81\x88\x83\xd8]\xbf\xc7H\xbc$\xbc#\x90\xe4\xbaJ\x9b\x11\x8e\x88[\xa8=|z`O\x8e\xbf\x9eNگ\xcckO-\x9c\xab\x06\x1f\xa1O\x90\x9cz\xb6\xef\xa9\x1a 럖\xf3f\x9c\x81\v\xef\xd0\x1cB7\xb3\xfe\xa7\xd7\xfe\xb8G\xbd\x1a\u007f\xfaeռFs\x16\x81\xac\u007fo,\xe6\x81\x1f\xff\xa8[\"JW\x99z{M*\xc3\x0fN\x10\x11\xf4\xef1\x9c\xf6\xc4O\xfb\xdcٌ,\xdb\a\xd0\xda\b\xc3\xecsk#\xf2k\x1e\v\x9a|=\xc7\xef\xae\xfe9\xb4\x15\xd1?M\x9c\xa3\xeb\x80\x1f蘙\xe9'j\xd3\u070e\xd7@s\xc7\xf0\xb0\xc7\xdd\x14\xeb\xe3ם+\xf8\x88\xcf#\xb57\x8a&qx\x18\xf5w\x9a\x98r\x84b\xecy\xb3\xa3S\xdc5\xbd\xf8By\xc4Z\xf4\xcdܠ\xf9 R-\xf2\xbcC\xd1_\x1e\x8f\x89\xf5\x8fr\xeb\xc3F\t\xcd\xe9O\a-&\r\xd7Q\xa35e\xb0F\x97\xd4A\xa5E\xb3ô\xa3$\xf5\x1eޭ\xa96\a\xef\xac\xd4\v\x13~\xf9\xf5\xac]\xa3\"I\xb0t\xf5\xfdH\xf7\xfd\xc9\xf3s\xfe#9\xb8S\x1d\xda;\xc5\xf8\xbf' 2\xcde$\xf6m)\x98Nѹpfm\xf20\x8e\xb9\x1b\xf9Z\xe9\xeem\x8f:f0\x92\x18\xb5Mktj\x0fh=\x81ZS\xa9ބ$i\xfcK,\xc3$\xc9hf\xf3%\xf6\xe7\xebh\xd6\xc7Iz9(\xc6\xf9\xe5\f\xd3C\x94\x99\xfb\xb7\xa6E}\xd2\x16\xb3\x89N\xd64ׯύڀ\xfc\xbf\xd9\x1b\xb7\bw\x1eY\x96J\xff\xb0騞\f\xe8\xc1\x10Pp.\xf6\xedbB& \xf3I\xbe\x901\x82\xdd\n\x9aU<\x9f\\\xeb\xd3&\xa0\xa2c%\xb9\x9fpH\xf6\xe0'\xe3Z1x;\xd7\xf9,\x87כ\b\xcd'\xfdI\xff\x9br\x1c7\x86p\xd5w\x99P\xad>D\x8fk\x8c\xaf\xf7׀2X\xabv\x16k\x10\nK\xed\xac\xab\x88\xd4i^5c\xa9]\xf6\xa9W\nh\xa1\x10\xfb\xe4\xe5\x80\xeeV7\xc0\x8b\x9aO\xf9+ϰ;\xddR\xbd;/\x87˖ʥ[C\x9cݥ\x98\x15\xce\xdeD\xcaj\xf6rI\xafn\x1e\vB\xb6S\xd9qf\\\xb5Ƹ\x88,c\xb8\ta5ً\xcbd\xbe\x99\x84\xc7\xe2I\xed\xa7\x01s\u061d\xff\xf4c \xc3H\x86?\xff*.\xd39.s\xbd`s?߂߽\xbbZgӧ\xf6\xae1y\x89\x87\x9f\u007f)\xb2cl\x9e\xc6\x1d4^\xfe\x1d\x00\x00\xff\xff;,8\xce>\f\x00\x00"), - []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4VM\x8f\xdb6\x10\xbd\xebW\f\xd2C.\x95\x9c\xa0\x87\x16\xba\x05n\x0fA\xd3`\x11\xa7\xbe\x14=\xd0\xe4Ȟ.E\xb2\x9c\xa1\xdb\xed\xaf/HQ돕\xb7Y\xa0э\xc3\xe1\x9b7o>\xec\xa6m\xdbF\x05\xdabd\xf2\xae\a\x15\b\xff\x16t\xf9\xc4\xdd\xfd\x0fܑ_\x1d\xdf6\xf7\xe4L\x0f\xeb\xc4\xe2\xc7O\xc8>E\x8d?\xe2@\x8e\x84\xbckF\x14e\x94\xa8\xbe\x01P\xceyQ\xd9\xcc\xf9\b\xa0\xbd\x93\xe8\xad\xc5\xd8\xee\xd1u\xf7i\x87\xbbD\xd6`,\xe0s\xe8\xe3\x9b\xee\xfb\xeeM\x03\xa0#\x96\xe7\x9fiD\x165\x86\x1e\\\xb2\xb6\x01pj\xc4\x1e\x8eަ\x11٩\xc0\a/\xd6\xeb)XwD\x8b\xd1w\xe4\x1b\x0e\xa8s\xec}\xf4)\xf4p\xba\x98 *\xaf)\xa7mA\xdbT\xb4\x0f\x15\xad8Xb\xf9\xf9\x19\xa7\x0f\xc4R\x1c\x83MQٛ̊\x0f\x93\xdb'\xab\xe2-\xaf\x06\x80\xb5\x0f\xd8\xc3\xc7L1(\x8d\xa6\x01\xa8\xf2\x14\xca\xed,\xc0\xdb\tQ\x1fpTS.\x00>\xa0{w\xf7~\xfb\xdd\xe6\xc2\f`\x90u\xa4 E\xe4\xe5D\x80\x18\x14\xccL\xe0\xaf\x03F\x84mQ\rX|D\xae\xa4\x1fA\x01f\xfe\xdc=\x1aC\xf4\x01\xa3\xd0,\xf0\xf4\x9d\xb5י\xf5\x8a\xd7\xebL}\xf2\x02\x93\xfb\n\x19\xe4\x80s\xfahj\xb6\xe0\a\x90\x031D\f\x11\x19\x9d\x9c\xcau\xfa\xfc\x00ʁ\xdf\xfd\x81Z:\xd8`\xcc0\xc0\a\x9f\xac\xc9\xedx\xc4(\x10Q\xfb\xbd\xa3\u007f\x1e\xb1\x19ė\xa0V\t\xd6ʞ>r\x82\xd1)\vGe\x13~\v\xca\x19\x18\xd5\x03D\xccQ \xb93\xbc\xe2\xc2\x1d\xfc\xe2#\x02\xb9\xc1\xf7p\x10\tܯV{\x92y\xac\xb4\x1f\xc7\xe4H\x1eVeBh\x97\xc4G^\x19<\xa2]1\xed[\x15\xf5\x81\x04\xb5\xa4\x88+\x15\xa8-\xd4\xdd\xd4\xed\xa3\xf9&\xd6A\xe4\xd7\x17\\\xe5!w\x11K$\xb7?\xbb(\xed\xfeL\x05r\xa7O\x8d0=\x9d\xb28\t\x9dMY\x9dO?m>\xc3\x1c\xba\x14\xe3Z\xfd\xa2\xfb\xe9!\x9fJ\x90\x05#7`\x9c\x8a8D?\x16Lt&xrR\x0e\xda\x12\xbak\xf99\xedF\x92\\\xf7?\x13\xb2\xe4Zu\xb0.\xbb\x06v\b)\x18%h:x\xef`\xadF\xb4k\xc5\xf8\xd5\v\x90\x95\xe66\v\xfbe%8_\x93\xd7Γj\xe7\x03V\x97؍z-O\xf2&\xa0\xbe\x18\xa0\x8cB\x03\xd5\xc9\x1e|\xbc\xd2U\xcds\xbe\x8c\xd7]\xb8/\x0f8L;~\xa0\xfd\xb5\x15@\x19S~!\x94\xbd\xbb\xf9\xf6\x19\xc1\x16\xf2^\x97H\xb9Q\a\x1f3\xa3#\x19\x8c\xed\x9cge\x92bM\x98\xd0\x1a\xee\x9e@\xdeм&Y \x9fҼ\xe0qW\xdd2\x93,\xf4\xfcl\xdaPX\x17fY\x9fj\x8f\xb7\x18,d\x9c;\x9c\"^\xcdj\xfb\x18\xe0\x8bzG\x94$~y\xf7\x94g\xd5sW;H\xa7\x18\xd1I\xc5\\ش\xffO\a\x85\x83b\xfc\x0f͗#\xdc\xe5\x97s\x19,\r\xa8\x1f\xb4\xc5\t\x10\xfc\xb0\xd0m/\xa2\x9c?ti|ʭ\x85wGEV\xed,.\xdc\xfd\xea\xd4\xcdۛ\xc5_\xac\xe7\x13#\xe7ujz\x90\x98&\xec\xdae\xd5r\xaa\xbe\xd2\x1a\x83\xa0\xf9x\xfd\xaf\xe7ի\x8b?.娽\x9b\x86\x95{\xf8\xed\xf7fBE\xb3\x9d\xff\x81d\xe3\xbf\x01\x00\x00\xff\xff\xbf\xca\xff\xa71\n\x00\x00"), + []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4WM\x93\xdb6\x0f\xbe\xfbW`\x92\xc3^\"9\x99\xf7\xf0vt\xe9d6=d\x9a\x8f\x9dx\xbb\x97N\x0f4\tY\xac)R\x05Ho\xdd_\xdf\x01)\xad\xbf\xe4d\xd3iu\xf1\b\x02\xc1\a\x0f\xf0\x80\xf4\xa2\xaa\xaa\x85\x1a\xec\x03\x12\xdb\xe0\x1bP\x83\xc5?#zy\xe3z\xfb\x03\xd76,wo\x16[\xebM\x03\xb7\x89c\xe8\xbf \x87D\x1a\xdfak\xbd\x8d6\xf8E\x8fQ\x19\x15U\xb3\x00Pއ\xa8\xc4\xcc\xf2\n\xa0\x83\x8f\x14\x9cC\xaa6\xe8\xebmZ\xe3:Yg\x90r\xf0i\xeb\xdd\xeb\xfa\xff\xf5\xeb\x05\x80&\xcc\xcb\xefm\x8f\x1cU?4\xe0\x93s\v\x00\xafzl`\x17\\ꑽ\x1a\xb8\v\xd1\x05]6\xabw\xe8\x90BmÂ\aԲ\xf7\x86B\x1a\x1a8|(!F\\%\xa7\x87\x1cm5F\xfb0F\xcb\x0e\xcer\xfc\xf9+N\x1f,\xc7\xec8\xb8D\xca]E\x96}\xd8\xfaMr\x8a\xaey-\x00X\x87\x01\x1b\xf8$\x10\a\xa5\xd1,\x00Fz2\xe4j\"\xe0M\x89\xa8;\xecU\xc9\x05 \f\xe8\xdf\u07bd\u007f\xf8\xdf\xea\xc4\f`\x905\xd9!f\x92\xe7\x13\x01ˠ`B\x02\x8f\x1d\x12\xc2Cf\r8\x06B\x1eA?\x05\x05\x98\xf0s\xfdd\x1c(\fH\xd1N\x04\x97稽\x8e\xacg\xb8n\x04z\xf1\x02#}\x85\f\xb1\xc3)}4c\xb6\x10Z\x88\x9de \x1c\b\x19}<\x94\xeb\xf0\x84\x16\x94\x87\xb0\xfe\x1du\xaca\x85$a\x80\xbb\x90\x9c\x91v\xdc!E \xd4a\xe3\xed_O\xb1\x19bț:\x15q\xac\xec\xe1\xb1>\"y\xe5`\xa7\\\xc2W\xa0\xbc\x81^\xed\x81Pv\x81\xe4\x8f\xe2e\x17\xae\xe1c \x04\xeb\xdb\xd0@\x17\xe3\xc0\xcdr\xb9\xb1q\x92\x95\x0e}\x9f\xbc\x8d\xfbeV\x88]\xa7\x18\x88\x97\x06w\xe8\x96l7\x95\"\xddو:&¥\x1al\x95\xa1\xfb\xd2\xed\xbdyI\xa3\x10\xf9\xe6\x04k\xdcK\x17q$\xeb7G\x1fr\xbb\u007f\xa5\x02\xd2\xe9\xa5\x11\xcaҒŁh1\t;_~Z\xddôu.\xc69\xfb\x99\xf7\xc3B>\x94@\b\xb3\xbeE*El)\xf49&z3\x04\xebc~\xd1\u03a2?\xa7\x9fӺ\xb7Q\xea\xfeGB\x8eR\xab\x1an\xf3\xac\x815B\x1a\x8c\x8ahjx\xef\xe1V\xf5\xe8n\x15\xe3\u007f^\x00a\x9a+!\xf6y%8\x1e\x93\xe7΅\xb5c\x81\x8dC\xecJ\xbd敼\x1aP\x9f\bH\xa2\xd8֎\xcan\x03\x9d\xf1\xaa&\x9d\xcfǫO\xdc\xe7\x05\x0eeƷvsn\x05P\xc6\xe4\x13B\xb9\xbb\xabk\xbfB\xd8L\u07b7y'i\xd46\x90 \xdaY\x83TMy\x8eH\x12\x8d\t[t\x86닐W8ϩ\x10\x1a\xa9\xb1r\x97@O\x91<9\xe6#NY_(?\x04ȭG\xfd8c}Do\xf2P\xbf@\x13r\x0f3\x1ax\xb4\xb1+\xe2p\xc7G\xd1\xf3\xaa \xcf\x16\xf7s\xe63\xec\xf7\x1d\x8ag\x19\xa7\b\x8c\x9a0\n\x0eF'\xe2\x15e\xd6\x00\x1f\x13gy\xa9و #\u009ai\xf5\x16\xf7\x97D÷\x8a;\x9e\xea߆|#\xe7\xe2\x04\x98\xb0EB\x1fg%.7\f\xf2\x181\xab\xdc\x04\xcd\"p\x8dC\xe4e\xd8!\xed,>.\x1f\x03m\xad\xdfTBxU\x1a\x81\x97\xf9v\xb0|\x99\u007f\xae\xa4|\xff\xf9\xdd\xe7\x06\xde\x1a\x03!vHR\xb56\xb9\xa9юN\xbbWy⾂d͏7\xff\x84\x970\x14\xe5<\x83\x9bU\xee\xfe\xbd\x9c\xdc\x19\x94P\xb4*U\t\x0427\xa5\xd8\xfdX\xcd2\x1f\xe6\x1aq´\x0e\xc1\xa1\xbal=\x99\xbe\x96\xd0\\B\xaad\x87\xef\x91٤\xdco\x88\xecnt\x13\xc1KVӲ\xa9\x11ʽ$\xdfR\xd4\x06\xaf\t}\x86\xe3\xf9T\xaa\xa7\r\x9e5\xa2\xa3\x8a\x89\xbf\u007fH\xe7e\xa3\xe7z\x1c\xd4:\x914\xf4\x18s\xe6B\xf3\xef\f\xea\xa1S<\xa3\xb6g\xa0\xbe\x93\x95S\x19\x9cmQ\xef\xb5\xc3\x12\x10B;\xd3M\xdf\x05Y\x1e\xf4\xa9\x9fk\xad\xb7;e\x9dZ;\x9c\xf9\xf6\x8bWW\xbf^-\xfel=/\x8c,\xb7\x16\xd3@\xa4Tb\x8f]6Z\x0e\xd5WZ\x86\v\x9aO\xe7\u007f.^\xbc8\xf9\u007f\x90_u\xf0\xe5L\xe4\x06~\xfdmQ\xa2\xa2y\x98.\xfab\xfc;\x00\x00\xff\xffji\x0e\x9c\x98\r\x00\x00"), } var CRDs = crds() diff --git a/pkg/apis/velero/v1/volume_snapshot_location.go b/pkg/apis/velero/v1/volume_snapshot_location.go index a2ba652a65..ed7c1a3a51 100644 --- a/pkg/apis/velero/v1/volume_snapshot_location.go +++ b/pkg/apis/velero/v1/volume_snapshot_location.go @@ -16,7 +16,10 @@ limitations under the License. package v1 -import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +import ( + corev1api "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -55,6 +58,10 @@ type VolumeSnapshotLocationSpec struct { // Config is for provider-specific configuration fields. // +optional Config map[string]string `json:"config,omitempty"` + + // Credential contains the credential information intended to be used with this location + // +optional + Credential *corev1api.SecretKeySelector `json:"credential,omitempty"` } // VolumeSnapshotLocationPhase is the lifecycle phase of a Velero VolumeSnapshotLocation. diff --git a/pkg/apis/velero/v1/zz_generated.deepcopy.go b/pkg/apis/velero/v1/zz_generated.deepcopy.go index 4c905d4f7e..4692970631 100644 --- a/pkg/apis/velero/v1/zz_generated.deepcopy.go +++ b/pkg/apis/velero/v1/zz_generated.deepcopy.go @@ -1603,6 +1603,11 @@ func (in *VolumeSnapshotLocationSpec) DeepCopyInto(out *VolumeSnapshotLocationSp (*out)[key] = val } } + if in.Credential != nil { + in, out := &in.Credential, &out.Credential + *out = new(corev1.SecretKeySelector) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshotLocationSpec. diff --git a/pkg/builder/volume_snapshot_location_builder.go b/pkg/builder/volume_snapshot_location_builder.go index 1862045e0b..af94471e36 100644 --- a/pkg/builder/volume_snapshot_location_builder.go +++ b/pkg/builder/volume_snapshot_location_builder.go @@ -1,5 +1,5 @@ /* -Copyright 2019 the Velero contributors. +Copyright the Velero contributors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,6 +19,8 @@ package builder import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + corev1api "k8s.io/api/core/v1" + velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" ) @@ -62,3 +64,9 @@ func (b *VolumeSnapshotLocationBuilder) Provider(name string) *VolumeSnapshotLoc b.object.Spec.Provider = name return b } + +// Credential sets the VolumeSnapshotLocation's credential selector. +func (b *VolumeSnapshotLocationBuilder) Credential(selector *corev1api.SecretKeySelector) *VolumeSnapshotLocationBuilder { + b.object.Spec.Credential = selector + return b +} diff --git a/pkg/cmd/cli/snapshotlocation/create.go b/pkg/cmd/cli/snapshotlocation/create.go index 824156eac5..f0cb2bf82b 100644 --- a/pkg/cmd/cli/snapshotlocation/create.go +++ b/pkg/cmd/cli/snapshotlocation/create.go @@ -26,6 +26,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "github.com/vmware-tanzu/velero/pkg/builder" "github.com/vmware-tanzu/velero/pkg/client" "github.com/vmware-tanzu/velero/pkg/cmd" "github.com/vmware-tanzu/velero/pkg/cmd/util/flag" @@ -54,15 +55,19 @@ func NewCreateCommand(f client.Factory, use string) *cobra.Command { } type CreateOptions struct { - Name string - Provider string - Config flag.Map - Labels flag.Map + Name string + Provider string + Config flag.Map + Labels flag.Map + Credential flag.Map + secretName string + secretKey string } func NewCreateOptions() *CreateOptions { return &CreateOptions{ - Config: flag.NewMap(), + Config: flag.NewMap(), + Credential: flag.NewMap(), } } @@ -70,6 +75,7 @@ func (o *CreateOptions) BindFlags(flags *pflag.FlagSet) { flags.StringVar(&o.Provider, "provider", o.Provider, "Name of the volume snapshot provider (e.g. aws, azure, gcp).") flags.Var(&o.Config, "config", "Configuration key-value pairs.") flags.Var(&o.Labels, "labels", "Labels to apply to the volume snapshot location.") + flags.Var(&o.Credential, "credential", "The credential to be used by this location as a key-value pair, where the key is the Kubernetes Secret name, and the value is the data key name within the Secret. Optional, one value only.") } func (o *CreateOptions) Validate(c *cobra.Command, args []string, f client.Factory) error { @@ -81,6 +87,15 @@ func (o *CreateOptions) Validate(c *cobra.Command, args []string, f client.Facto return errors.New("--provider is required") } + if len(o.Credential.Data()) > 1 { + return errors.New("--credential can only contain 1 key/value pair") + } + + for k, v := range o.Credential.Data() { + o.secretName = k + o.secretKey = v + break + } return nil } @@ -97,8 +112,9 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { Labels: o.Labels.Data(), }, Spec: api.VolumeSnapshotLocationSpec{ - Provider: o.Provider, - Config: o.Config.Data(), + Provider: o.Provider, + Config: o.Config.Data(), + Credential: builder.ForSecretKeySelector(o.secretName, o.secretKey).Result(), }, } diff --git a/pkg/cmd/cli/snapshotlocation/set.go b/pkg/cmd/cli/snapshotlocation/set.go index 8515426610..f6b8ac3688 100644 --- a/pkg/cmd/cli/snapshotlocation/set.go +++ b/pkg/cmd/cli/snapshotlocation/set.go @@ -27,8 +27,10 @@ import ( kbclient "sigs.k8s.io/controller-runtime/pkg/client" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "github.com/vmware-tanzu/velero/pkg/builder" "github.com/vmware-tanzu/velero/pkg/client" "github.com/vmware-tanzu/velero/pkg/cmd" + "github.com/vmware-tanzu/velero/pkg/cmd/util/flag" "github.com/vmware-tanzu/velero/pkg/cmd/util/output" ) @@ -39,9 +41,6 @@ func NewSetCommand(f client.Factory, use string) *cobra.Command { Use: use + " NAME", Short: "Set specific features for a snapshot location", Args: cobra.ExactArgs(1), - // Mark this command as hidden until more functionality is added - // as part of https://github.com/vmware-tanzu/velero/issues/2426 - Hidden: true, Run: func(c *cobra.Command, args []string) { cmd.CheckError(o.Complete(args, f)) cmd.CheckError(o.Validate(c, args, f)) @@ -54,14 +53,18 @@ func NewSetCommand(f client.Factory, use string) *cobra.Command { } type SetOptions struct { - Name string + Name string + Credential flag.Map } func NewSetOptions() *SetOptions { - return &SetOptions{} + return &SetOptions{ + Credential: flag.NewMap(), + } } -func (o *SetOptions) BindFlags(*pflag.FlagSet) { +func (o *SetOptions) BindFlags(flags *pflag.FlagSet) { + flags.Var(&o.Credential, "credential", "Sets the credential to be used by this location as a key-value pair, where the key is the Kubernetes Secret name, and the value is the data key name within the Secret. Optional, one value only.") } func (o *SetOptions) Validate(c *cobra.Command, args []string, f client.Factory) error { @@ -69,6 +72,10 @@ func (o *SetOptions) Validate(c *cobra.Command, args []string, f client.Factory) return err } + if len(o.Credential.Data()) > 1 { + return errors.New("--credential can only contain 1 key/value pair") + } + return nil } @@ -92,6 +99,11 @@ func (o *SetOptions) Run(c *cobra.Command, f client.Factory) error { return errors.WithStack(err) } + for name, key := range o.Credential.Data() { + location.Spec.Credential = builder.ForSecretKeySelector(name, key).Result() + break + } + if err := kbClient.Update(context.Background(), location, &kbclient.UpdateOptions{}); err != nil { return errors.WithStack(err) } diff --git a/pkg/cmd/server/server.go b/pkg/cmd/server/server.go index 271051f674..9eb1354711 100644 --- a/pkg/cmd/server/server.go +++ b/pkg/cmd/server/server.go @@ -649,6 +649,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string csiVSCLister, csiVSClassLister, backupStoreGetter, + s.credentialFileStore, ) return controllerRunInfo{ @@ -713,6 +714,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string s.logger, podexec.NewPodCommandExecutor(s.kubeClientConfig, s.kubeClient.CoreV1().RESTClient()), s.kubeClient.CoreV1().RESTClient(), + s.credentialFileStore, ) cmd.CheckError(err) diff --git a/pkg/controller/backup_controller.go b/pkg/controller/backup_controller.go index e7075a560f..031fa31591 100644 --- a/pkg/controller/backup_controller.go +++ b/pkg/controller/backup_controller.go @@ -44,6 +44,7 @@ import ( snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" snapshotv1listers "github.com/kubernetes-csi/external-snapshotter/client/v4/listers/volumesnapshot/v1" + "github.com/vmware-tanzu/velero/internal/credentials" "github.com/vmware-tanzu/velero/internal/storage" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" pkgbackup "github.com/vmware-tanzu/velero/pkg/backup" @@ -89,6 +90,7 @@ type backupController struct { volumeSnapshotLister snapshotv1listers.VolumeSnapshotLister volumeSnapshotContentLister snapshotv1listers.VolumeSnapshotContentLister volumeSnapshotClassLister snapshotv1listers.VolumeSnapshotClassLister + credentialFileStore credentials.FileStore } func NewBackupController( @@ -112,6 +114,7 @@ func NewBackupController( volumeSnapshotContentLister snapshotv1listers.VolumeSnapshotContentLister, volumesnapshotClassLister snapshotv1listers.VolumeSnapshotClassLister, backupStoreGetter persistence.ObjectBackupStoreGetter, + credentialStore credentials.FileStore, ) Interface { c := &backupController{ genericController: newGenericController(Backup, logger), @@ -135,6 +138,7 @@ func NewBackupController( volumeSnapshotContentLister: volumeSnapshotContentLister, volumeSnapshotClassLister: volumesnapshotClassLister, backupStoreGetter: backupStoreGetter, + credentialFileStore: credentialStore, } c.syncHandler = c.processBackup @@ -531,6 +535,15 @@ func (c *backupController) validateAndGetSnapshotLocations(backup *velerov1api.B return nil, errors } + // add credential to config for each location + for _, location := range providerLocations { + err = volume.UpdateVolumeSnapshotLocationWithCredentialConfig(location, c.credentialFileStore, c.logger) + if err != nil { + errors = append(errors, fmt.Sprintf("error adding credentials to volume snapshot location named %s: %v", location.Name, err)) + continue + } + } + return providerLocations, nil } diff --git a/pkg/controller/backup_controller_test.go b/pkg/controller/backup_controller_test.go index 85c581a81a..c0076affb4 100644 --- a/pkg/controller/backup_controller_test.go +++ b/pkg/controller/backup_controller_test.go @@ -998,12 +998,15 @@ func TestValidateAndGetSnapshotLocations(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + formatFlag := logging.FormatText var ( client = fake.NewSimpleClientset() sharedInformers = informers.NewSharedInformerFactory(client, 0) + logger = logging.DefaultLogger(logrus.DebugLevel, formatFlag) ) c := &backupController{ + genericController: newGenericController("backup-test", logger), snapshotLocationLister: sharedInformers.Velero().V1().VolumeSnapshotLocations().Lister(), defaultSnapshotLocations: test.defaultLocations, } diff --git a/pkg/restore/pv_restorer.go b/pkg/restore/pv_restorer.go index ff8d36b347..ce3ab1e1d9 100644 --- a/pkg/restore/pv_restorer.go +++ b/pkg/restore/pv_restorer.go @@ -21,6 +21,7 @@ import ( "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "github.com/vmware-tanzu/velero/internal/credentials" api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" listers "github.com/vmware-tanzu/velero/pkg/generated/listers/velero/v1" "github.com/vmware-tanzu/velero/pkg/util/boolptr" @@ -39,6 +40,7 @@ type pvRestorer struct { volumeSnapshots []*volume.Snapshot volumeSnapshotterGetter VolumeSnapshotterGetter snapshotLocationLister listers.VolumeSnapshotLocationLister + credentialFileStore credentials.FileStore } func (r *pvRestorer) executePVAction(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { @@ -59,7 +61,7 @@ func (r *pvRestorer) executePVAction(obj *unstructured.Unstructured) (*unstructu log := r.logger.WithFields(logrus.Fields{"persistentVolume": pvName}) - snapshotInfo, err := getSnapshotInfo(pvName, r.backup, r.volumeSnapshots, r.snapshotLocationLister) + snapshotInfo, err := getSnapshotInfo(pvName, r.backup, r.volumeSnapshots, r.snapshotLocationLister, r.credentialFileStore, r.logger) if err != nil { return nil, err } @@ -103,7 +105,7 @@ type snapshotInfo struct { location *api.VolumeSnapshotLocation } -func getSnapshotInfo(pvName string, backup *api.Backup, volumeSnapshots []*volume.Snapshot, snapshotLocationLister listers.VolumeSnapshotLocationLister) (*snapshotInfo, error) { +func getSnapshotInfo(pvName string, backup *api.Backup, volumeSnapshots []*volume.Snapshot, snapshotLocationLister listers.VolumeSnapshotLocationLister, credentialStore credentials.FileStore, logger logrus.FieldLogger) (*snapshotInfo, error) { var pvSnapshot *volume.Snapshot for _, snapshot := range volumeSnapshots { if snapshot.Spec.PersistentVolumeName == pvName { @@ -120,6 +122,11 @@ func getSnapshotInfo(pvName string, backup *api.Backup, volumeSnapshots []*volum if err != nil { return nil, errors.WithStack(err) } + // add credential to config + err = volume.UpdateVolumeSnapshotLocationWithCredentialConfig(loc, credentialStore, logger) + if err != nil { + return nil, errors.WithStack(err) + } return &snapshotInfo{ providerSnapshotID: pvSnapshot.Status.ProviderSnapshotID, diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index 67681eea5e..cc5a46ee88 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -46,6 +46,7 @@ import ( corev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/cache" + "github.com/vmware-tanzu/velero/internal/credentials" "github.com/vmware-tanzu/velero/internal/hook" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "github.com/vmware-tanzu/velero/pkg/archive" @@ -113,6 +114,7 @@ type kubernetesRestorer struct { logger logrus.FieldLogger podCommandExecutor podexec.PodCommandExecutor podGetter cache.Getter + credentialFileStore credentials.FileStore } // NewKubernetesRestorer creates a new kubernetesRestorer. @@ -128,6 +130,7 @@ func NewKubernetesRestorer( logger logrus.FieldLogger, podCommandExecutor podexec.PodCommandExecutor, podGetter cache.Getter, + credentialStore credentials.FileStore, ) (Restorer, error) { return &kubernetesRestorer{ restoreClient: restoreClient, @@ -147,9 +150,10 @@ func NewKubernetesRestorer( veleroCloneName := "velero-clone-" + veleroCloneUuid.String() return veleroCloneName, nil }, - fileSystem: filesystem.NewFileSystem(), - podCommandExecutor: podCommandExecutor, - podGetter: podGetter, + fileSystem: filesystem.NewFileSystem(), + podCommandExecutor: podCommandExecutor, + podGetter: podGetter, + credentialFileStore: credentialStore, }, nil } @@ -254,6 +258,7 @@ func (kr *kubernetesRestorer) RestoreWithResolvers( volumeSnapshots: req.VolumeSnapshots, volumeSnapshotterGetter: volumeSnapshotterGetter, snapshotLocationLister: snapshotLocationLister, + credentialFileStore: kr.credentialFileStore, } restoreCtx := &restoreContext{ diff --git a/pkg/volume/snapshotlocation.go b/pkg/volume/snapshotlocation.go new file mode 100644 index 0000000000..19438e83bd --- /dev/null +++ b/pkg/volume/snapshotlocation.go @@ -0,0 +1,46 @@ +/* +Copyright the Velero contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package volume + +import ( + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + + "github.com/vmware-tanzu/velero/internal/credentials" + velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" +) + +// If the VSL specifies a credential, add credential file path to config +func UpdateVolumeSnapshotLocationWithCredentialConfig(location *velerov1api.VolumeSnapshotLocation, credentialStore credentials.FileStore, logger logrus.FieldLogger) error { + // add the bucket name and prefix to the config map so that object stores + // can use them when initializing. The AWS object store uses the bucket + // name to determine the bucket's region when setting up its client. + if location.Spec.Config == nil { + location.Spec.Config = make(map[string]string) + } + // If the VSL specifies a credential, fetch its path on disk and pass to + // plugin via the config. + if location.Spec.Credential != nil && credentialStore != nil { + credsFile, err := credentialStore.Path(location.Spec.Credential) + if err != nil { + return errors.Wrap(err, "unable to get credentials") + } + + location.Spec.Config["credentialsFile"] = credsFile + } + return nil +}