From 4013c92afb9593d288ee056d88c5e75079cfd216 Mon Sep 17 00:00:00 2001 From: Abigail McCarthy Date: Tue, 10 May 2022 13:46:52 -0400 Subject: [PATCH 01/28] Update compatibility matrix for 1.9 Signed-off-by: Abigail McCarthy --- README.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 36cc3baff..da18b502a 100644 --- a/README.md +++ b/README.md @@ -38,13 +38,22 @@ See [the list of releases][6] to find out about feature changes. The following is a list of the supported Kubernetes versions for each Velero version. -| Velero version | Kubernetes versions| -|----------------|--------------------| -| 1.8 | 1.16-latest | -| 1.6.3-1.7.1 | 1.12-latest | -| 1.60-1.6.2 | 1.12-1.21 | -| 1.5 | 1.12-1.21 | -| 1.4 | 1.10-1.21 | +| Velero version | Expected Kubernetes version compatibility| Tested on Kubernetes version| +|----------------|--------------------|--------------------| +| 1.9 | 1.16-latest | 1.20.5, 1.21.2, 1.22.5, 1.23, and 1.24 | +| 1.8 | 1.16-latest | | +| 1.6.3-1.7.1 | 1.12-latest || +| 1.60-1.6.2 | 1.12-1.21 || +| 1.5 | 1.12-1.21 || +| 1.4 | 1.10-1.21 | | + +The Velero maintainers are continuously working to expand testing coverage, but are not able to test every combination of Velero and supported Kubernetes for each Velero release. The table above is meant to track the current testing coverage and the expected supported Kubernetes versions and configurations. + +Velero also supports IPv4, IPv6, and dual stack environments. + +If you are interested in using a different version of Kubernetes with a given Velero version, we'd recommend that you perform testing before installing or upgrading your environment. + +For full information around capabilities within a release, also see the Velero [release notes](https://github.com/vmware-tanzu/velero/releases) and Kubernetes [release notes](https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG). [1]: https://github.com/vmware-tanzu/velero/workflows/Main%20CI/badge.svg [2]: https://github.com/vmware-tanzu/velero/actions?query=workflow%3A"Main+CI" From 6a721403fb7a9767bf0e25d5b3a659d2d14d7a20 Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Thu, 12 May 2022 10:46:48 -0300 Subject: [PATCH 02/28] Fix DeepEqual when status is updated Signed-off-by: Rafael Leal --- pkg/restore/restore.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index d22ddbc37..cbb335f27 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -1227,6 +1227,18 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso // and which backup they came from. addRestoreLabels(obj, ctx.restore.Name, ctx.restore.Spec.BackupName) + // Clear out status. + + objWithoutStatus := obj.DeepCopy() + if objWithoutStatus, err = resetStatus(objWithoutStatus); err != nil { + errs.Add(namespace, err) + return warnings, errs + } + if !shouldRestoreStatus { + ctx.log.Infof("Resetting status for obj %s/%s", obj.GetKind(), obj.GetName()) + obj = objWithoutStatus + } + ctx.log.Infof("Attempting to restore %s: %v", obj.GroupVersionKind().Kind, name) createdObj, restoreErr := resourceClient.Create(obj) isAlreadyExistsError, err := isAlreadyExistsError(ctx, obj, restoreErr, resourceClient) @@ -1255,7 +1267,7 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso addRestoreLabels(fromCluster, labels[velerov1api.RestoreNameLabel], labels[velerov1api.BackupNameLabel]) fromClusterWithLabels := fromCluster.DeepCopy() // saving the in-cluster object so that we can create label patch if overall patch fails - if !equality.Semantic.DeepEqual(fromCluster, obj) { + if !equality.Semantic.DeepEqual(fromCluster, objWithoutStatus) { switch groupResource { case kuberesource.ServiceAccounts: desired, err := mergeServiceAccounts(fromCluster, obj) From e374eb9da4e417d741d111955ec422987b638067 Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Fri, 25 Mar 2022 13:05:11 -0300 Subject: [PATCH 03/28] Add StatusUpdater Signed-off-by: Rafael Leal --- pkg/client/dynamic.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/client/dynamic.go b/pkg/client/dynamic.go index 114841805..8fcfab107 100644 --- a/pkg/client/dynamic.go +++ b/pkg/client/dynamic.go @@ -89,6 +89,11 @@ type Deletor interface { Delete(name string, opts metav1.DeleteOptions) error } +// StatusUpdater updates status field of a object +type StatusUpdater interface { + UpdateStatus(obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) +} + // Dynamic contains client methods that Velero needs for backing up and restoring resources. type Dynamic interface { Creator @@ -97,6 +102,7 @@ type Dynamic interface { Getter Patcher Deletor + StatusUpdater } // dynamicResourceClient implements Dynamic. @@ -129,3 +135,7 @@ func (d *dynamicResourceClient) Patch(name string, data []byte) (*unstructured.U func (d *dynamicResourceClient) Delete(name string, opts metav1.DeleteOptions) error { return d.resourceClient.Delete(context.TODO(), name, opts) } + +func (d *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) { + return d.resourceClient.UpdateStatus(context.TODO(), obj, opts) +} From 7f1f881c2813b0ee301f08931822cfd9aa8975fe Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Thu, 12 May 2022 11:58:47 -0300 Subject: [PATCH 04/28] Add resource status Signed-off-by: Rafael Leal --- pkg/apis/velero/v1/restore.go | 19 ++++ pkg/restore/restore.go | 168 ++++++++++++++++++++-------------- 2 files changed, 116 insertions(+), 71 deletions(-) diff --git a/pkg/apis/velero/v1/restore.go b/pkg/apis/velero/v1/restore.go index aab5b35c9..6dfb0a959 100644 --- a/pkg/apis/velero/v1/restore.go +++ b/pkg/apis/velero/v1/restore.go @@ -86,6 +86,12 @@ type RestoreSpec struct { // +nullable RestorePVs *bool `json:"restorePVs,omitempty"` + // RestoreStatus specifies which resources we should restore the status + // field. If nil, no objects are included. Optional. + // +optional + // +nullable + RestoreStatus *RestoreStatusSpec + // PreserveNodePorts specifies whether to restore old nodePorts from backup. // +optional // +nullable @@ -113,6 +119,19 @@ type RestoreHooks struct { Resources []RestoreResourceHookSpec `json:"resources,omitempty"` } +type RestoreStatusSpec struct { + // IncludedResources specifies the resources to which will restore the status. + // If empty, it applies to all resources. + // +optional + // +nullable + IncludedResources []string `json:"includedResources,omitempty"` + + // ExcludedResources specifies the resources to which will not restore the status. + // +optional + // +nullable + ExcludedResources []string `json:"excludedResources,omitempty"` +} + // RestoreResourceHookSpec defines one or more RestoreResrouceHooks that should be executed based on // the rules defined for namespaces, resources, and label selector. type RestoreResourceHookSpec struct { diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index cbb335f27..3761477be 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -206,6 +206,20 @@ func (kr *kubernetesRestorer) RestoreWithResolvers( req.Restore.Spec.ExcludedResources, ) + // Get resource status includes-excludes. Defaults to excluding all resources + restoreStatusIncludesExcludes := collections.GetResourceIncludesExcludes( + kr.discoveryHelper, + []string{}, + []string{"*"}, + ) + if req.Restore.Spec.RestoreStatus != nil { + restoreStatusIncludesExcludes = collections.GetResourceIncludesExcludes( + kr.discoveryHelper, + req.Restore.Spec.RestoreStatus.IncludedResources, + req.Restore.Spec.RestoreStatus.ExcludedResources, + ) + } + // Get namespace includes-excludes. namespaceIncludesExcludes := collections.NewIncludesExcludes(). Includes(req.Restore.Spec.IncludedNamespaces...). @@ -268,83 +282,85 @@ func (kr *kubernetesRestorer) RestoreWithResolvers( } restoreCtx := &restoreContext{ - backup: req.Backup, - backupReader: req.BackupReader, - restore: req.Restore, - resourceIncludesExcludes: resourceIncludesExcludes, - namespaceIncludesExcludes: namespaceIncludesExcludes, - chosenGrpVersToRestore: make(map[string]ChosenGroupVersion), - selector: selector, - OrSelectors: OrSelectors, - log: req.Log, - dynamicFactory: kr.dynamicFactory, - fileSystem: kr.fileSystem, - namespaceClient: kr.namespaceClient, - restoreItemActions: resolvedActions, - itemSnapshotterActions: resolvedItemSnapshotterActions, - volumeSnapshotterGetter: volumeSnapshotterGetter, - resticRestorer: resticRestorer, - resticErrs: make(chan error), - pvsToProvision: sets.NewString(), - pvRestorer: pvRestorer, - volumeSnapshots: req.VolumeSnapshots, - podVolumeBackups: req.PodVolumeBackups, - resourceTerminatingTimeout: kr.resourceTerminatingTimeout, - resourceClients: make(map[resourceClientKey]client.Dynamic), - restoredItems: make(map[velero.ResourceIdentifier]struct{}), - renamedPVs: make(map[string]string), - pvRenamer: kr.pvRenamer, - discoveryHelper: kr.discoveryHelper, - resourcePriorities: kr.resourcePriorities, - resourceRestoreHooks: resourceRestoreHooks, - hooksErrs: make(chan error), - waitExecHookHandler: waitExecHookHandler, - hooksContext: hooksCtx, - hooksCancelFunc: hooksCancelFunc, - restoreClient: kr.restoreClient, + backup: req.Backup, + backupReader: req.BackupReader, + restore: req.Restore, + resourceIncludesExcludes: resourceIncludesExcludes, + resourceStatusIncludesExcludes: restoreStatusIncludesExcludes, + namespaceIncludesExcludes: namespaceIncludesExcludes, + chosenGrpVersToRestore: make(map[string]ChosenGroupVersion), + selector: selector, + OrSelectors: OrSelectors, + log: req.Log, + dynamicFactory: kr.dynamicFactory, + fileSystem: kr.fileSystem, + namespaceClient: kr.namespaceClient, + restoreItemActions: resolvedActions, + itemSnapshotterActions: resolvedItemSnapshotterActions, + volumeSnapshotterGetter: volumeSnapshotterGetter, + resticRestorer: resticRestorer, + resticErrs: make(chan error), + pvsToProvision: sets.NewString(), + pvRestorer: pvRestorer, + volumeSnapshots: req.VolumeSnapshots, + podVolumeBackups: req.PodVolumeBackups, + resourceTerminatingTimeout: kr.resourceTerminatingTimeout, + resourceClients: make(map[resourceClientKey]client.Dynamic), + restoredItems: make(map[velero.ResourceIdentifier]struct{}), + renamedPVs: make(map[string]string), + pvRenamer: kr.pvRenamer, + discoveryHelper: kr.discoveryHelper, + resourcePriorities: kr.resourcePriorities, + resourceRestoreHooks: resourceRestoreHooks, + hooksErrs: make(chan error), + waitExecHookHandler: waitExecHookHandler, + hooksContext: hooksCtx, + hooksCancelFunc: hooksCancelFunc, + restoreClient: kr.restoreClient, } return restoreCtx.execute() } type restoreContext struct { - backup *velerov1api.Backup - backupReader io.Reader - restore *velerov1api.Restore - restoreDir string - restoreClient velerov1client.RestoresGetter - resourceIncludesExcludes *collections.IncludesExcludes - namespaceIncludesExcludes *collections.IncludesExcludes - chosenGrpVersToRestore map[string]ChosenGroupVersion - selector labels.Selector - OrSelectors []labels.Selector - log logrus.FieldLogger - dynamicFactory client.DynamicFactory - fileSystem filesystem.Interface - namespaceClient corev1.NamespaceInterface - restoreItemActions []framework.RestoreItemResolvedAction - itemSnapshotterActions []framework.ItemSnapshotterResolvedAction - volumeSnapshotterGetter VolumeSnapshotterGetter - resticRestorer restic.Restorer - resticWaitGroup sync.WaitGroup - resticErrs chan error - pvsToProvision sets.String - pvRestorer PVRestorer - volumeSnapshots []*volume.Snapshot - podVolumeBackups []*velerov1api.PodVolumeBackup - resourceTerminatingTimeout time.Duration - resourceClients map[resourceClientKey]client.Dynamic - restoredItems map[velero.ResourceIdentifier]struct{} - renamedPVs map[string]string - pvRenamer func(string) (string, error) - discoveryHelper discovery.Helper - resourcePriorities []string - hooksWaitGroup sync.WaitGroup - hooksErrs chan error - resourceRestoreHooks []hook.ResourceRestoreHook - waitExecHookHandler hook.WaitExecHookHandler - hooksContext go_context.Context - hooksCancelFunc go_context.CancelFunc + backup *velerov1api.Backup + backupReader io.Reader + restore *velerov1api.Restore + restoreDir string + restoreClient velerov1client.RestoresGetter + resourceIncludesExcludes *collections.IncludesExcludes + resourceStatusIncludesExcludes *collections.IncludesExcludes + namespaceIncludesExcludes *collections.IncludesExcludes + chosenGrpVersToRestore map[string]ChosenGroupVersion + selector labels.Selector + OrSelectors []labels.Selector + log logrus.FieldLogger + dynamicFactory client.DynamicFactory + fileSystem filesystem.Interface + namespaceClient corev1.NamespaceInterface + restoreItemActions []framework.RestoreItemResolvedAction + itemSnapshotterActions []framework.ItemSnapshotterResolvedAction + volumeSnapshotterGetter VolumeSnapshotterGetter + resticRestorer restic.Restorer + resticWaitGroup sync.WaitGroup + resticErrs chan error + pvsToProvision sets.String + pvRestorer PVRestorer + volumeSnapshots []*volume.Snapshot + podVolumeBackups []*velerov1api.PodVolumeBackup + resourceTerminatingTimeout time.Duration + resourceClients map[resourceClientKey]client.Dynamic + restoredItems map[velero.ResourceIdentifier]struct{} + renamedPVs map[string]string + pvRenamer func(string) (string, error) + discoveryHelper discovery.Helper + resourcePriorities []string + hooksWaitGroup sync.WaitGroup + hooksErrs chan error + resourceRestoreHooks []hook.ResourceRestoreHook + waitExecHookHandler hook.WaitExecHookHandler + hooksContext go_context.Context + hooksCancelFunc go_context.CancelFunc } type resourceClientKey struct { @@ -1356,6 +1372,16 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso return warnings, errs } + // if it should restore status, run a UpdateStatus + if ctx.resourceStatusIncludesExcludes.ShouldInclude(groupResource.String()) { + updated, err := resourceClient.UpdateStatus(obj, metav1.UpdateOptions{}) + if err != nil { + warnings.Add(namespace, err) + } else { + createdObj = updated + } + } + if groupResource == kuberesource.Pods { pod := new(v1.Pod) if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), pod); err != nil { From 0b9d6ae73d5322cd5ed02bdd43879c56c37aa20f Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Mon, 28 Mar 2022 14:52:01 -0300 Subject: [PATCH 05/28] Add restore status mechanism Signed-off-by: Rafael Leal --- pkg/apis/velero/v1/restore.go | 2 +- pkg/restore/restore.go | 36 +++++++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/pkg/apis/velero/v1/restore.go b/pkg/apis/velero/v1/restore.go index 6dfb0a959..251f1a045 100644 --- a/pkg/apis/velero/v1/restore.go +++ b/pkg/apis/velero/v1/restore.go @@ -90,7 +90,7 @@ type RestoreSpec struct { // field. If nil, no objects are included. Optional. // +optional // +nullable - RestoreStatus *RestoreStatusSpec + RestoreStatus *RestoreStatusSpec `json:"restoreStatus,omitempty"` // PreserveNodePorts specifies whether to restore old nodePorts from backup. // +optional diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index 3761477be..b13e97f4c 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -1127,19 +1127,30 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso } } - // Clear out non-core metadata fields and status. - if obj, err = resetMetadataAndStatus(obj); err != nil { + // Clear out non-core metadata fields. + if obj, err = resetMetadata(obj); err != nil { errs.Add(namespace, err) return warnings, errs } + shouldRestoreStatus := ctx.resourceStatusIncludesExcludes.ShouldInclude(groupResource.String()) + + ctx.log.Infof("restore status includes excludes: %+v", ctx.resourceStatusIncludesExcludes) + // Clear out status. + if !shouldRestoreStatus { + ctx.log.Infof("Resetting status for obj %s/%s", obj.GetKind(), obj.GetName()) + if obj, err = resetStatus(obj); err != nil { + errs.Add(namespace, err) + return warnings, errs + } + } + for _, action := range ctx.getApplicableActions(groupResource, namespace) { if !action.Selector.Matches(labels.Set(obj.GetLabels())) { continue } ctx.log.Infof("Executing item action for %v", &groupResource) - executeOutput, err := action.RestoreItemAction.Execute(&velero.RestoreItemActionExecuteInput{ Item: obj, ItemFromBackup: itemFromBackup, @@ -1270,12 +1281,18 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso return warnings, errs } // Remove insubstantial metadata. - fromCluster, err = resetMetadataAndStatus(fromCluster) + fromCluster, err = resetMetadata(fromCluster) if err != nil { ctx.log.Infof("Error trying to reset metadata for %s: %v", kube.NamespaceAndName(obj), err) warnings.Add(namespace, err) return warnings, errs } + fromCluster, err = resetStatus(fromCluster) + if err != nil { + ctx.log.Infof("Error trying to reset status for %s: %v", kube.NamespaceAndName(obj), err) + warnings.Add(namespace, err) + return warnings, errs + } // We know the object from the cluster won't have the backup/restore name // labels, so copy them from the object we attempted to restore. @@ -1373,7 +1390,8 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso } // if it should restore status, run a UpdateStatus - if ctx.resourceStatusIncludesExcludes.ShouldInclude(groupResource.String()) { + if shouldRestoreStatus { + obj.SetResourceVersion(createdObj.GetResourceVersion()) updated, err := resourceClient.UpdateStatus(obj, metav1.UpdateOptions{}) if err != nil { warnings.Add(namespace, err) @@ -1669,7 +1687,7 @@ func resetVolumeBindingInfo(obj *unstructured.Unstructured) *unstructured.Unstru return obj } -func resetMetadataAndStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { +func resetMetadata(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { res, ok := obj.Object["metadata"] if !ok { return nil, errors.New("metadata not found") @@ -1687,9 +1705,11 @@ func resetMetadataAndStatus(obj *unstructured.Unstructured) (*unstructured.Unstr } } - // Never restore status - delete(obj.UnstructuredContent(), "status") + return obj, nil +} +func resetStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + delete(obj.UnstructuredContent(), "status") return obj, nil } From 04aa7a849fb754ad9e8742a879a233ad31caf78d Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Mon, 28 Mar 2022 14:52:54 -0300 Subject: [PATCH 06/28] Fixes tests hopefully Signed-off-by: Rafael Leal --- pkg/apis/velero/v1/zz_generated.deepcopy.go | 31 ++++++++++++++++ pkg/restore/restore.go | 1 + pkg/restore/restore_test.go | 39 +++++++++++++++++++-- pkg/test/fake_dynamic.go | 5 +++ 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/pkg/apis/velero/v1/zz_generated.deepcopy.go b/pkg/apis/velero/v1/zz_generated.deepcopy.go index aee977c6d..8b3175700 100644 --- a/pkg/apis/velero/v1/zz_generated.deepcopy.go +++ b/pkg/apis/velero/v1/zz_generated.deepcopy.go @@ -1278,6 +1278,11 @@ func (in *RestoreSpec) DeepCopyInto(out *RestoreSpec) { *out = new(bool) **out = **in } + if in.RestoreStatus != nil { + in, out := &in.RestoreStatus, &out.RestoreStatus + *out = new(RestoreStatusSpec) + (*in).DeepCopyInto(*out) + } if in.PreserveNodePorts != nil { in, out := &in.PreserveNodePorts, &out.PreserveNodePorts *out = new(bool) @@ -1334,6 +1339,32 @@ func (in *RestoreStatus) DeepCopy() *RestoreStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RestoreStatusSpec) DeepCopyInto(out *RestoreStatusSpec) { + *out = *in + if in.IncludedResources != nil { + in, out := &in.IncludedResources, &out.IncludedResources + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ExcludedResources != nil { + in, out := &in.ExcludedResources, &out.ExcludedResources + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreStatusSpec. +func (in *RestoreStatusSpec) DeepCopy() *RestoreStatusSpec { + if in == nil { + return nil + } + out := new(RestoreStatusSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Schedule) DeepCopyInto(out *Schedule) { *out = *in diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index b13e97f4c..835b393bb 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -1009,6 +1009,7 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso } if groupResource == kuberesource.PersistentVolumes { + resetStatus(obj) switch { case hasSnapshot(name, ctx.volumeSnapshots): oldName := obj.GetName() diff --git a/pkg/restore/restore_test.go b/pkg/restore/restore_test.go index 973c91cb8..87528a627 100644 --- a/pkg/restore/restore_test.go +++ b/pkg/restore/restore_test.go @@ -1867,6 +1867,7 @@ func assertRestoredItems(t *testing.T, h *harness, want []*test.APIResource) { // empty in the structured objects. Remove them to make comparison easier. unstructured.RemoveNestedField(want.Object, "metadata", "creationTimestamp") unstructured.RemoveNestedField(want.Object, "status") + unstructured.RemoveNestedField(res.Object, "status") assert.Equal(t, want, res) } @@ -2805,7 +2806,7 @@ func TestRestoreWithRestic(t *testing.T) { } } -func TestResetMetadataAndStatus(t *testing.T) { +func TestResetMetadata(t *testing.T) { tests := []struct { name string obj *unstructured.Unstructured @@ -2824,7 +2825,39 @@ func TestResetMetadataAndStatus(t *testing.T) { expectedRes: NewTestUnstructured().WithMetadata("name", "namespace", "labels", "annotations").Unstructured, }, { - name: "don't keep status", + name: "keep status", + obj: NewTestUnstructured().WithMetadata().WithStatus().Unstructured, + expectedErr: false, + expectedRes: NewTestUnstructured().WithMetadata().WithStatus().Unstructured, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + res, err := resetMetadata(test.obj) + + if assert.Equal(t, test.expectedErr, err != nil) { + assert.Equal(t, test.expectedRes, res) + } + }) + } +} + +func TestResetStatus(t *testing.T) { + tests := []struct { + name string + obj *unstructured.Unstructured + expectedErr bool + expectedRes *unstructured.Unstructured + }{ + { + name: "no metadata don't cause error", + obj: &unstructured.Unstructured{}, + expectedErr: false, + expectedRes: &unstructured.Unstructured{}, + }, + { + name: "remove status", obj: NewTestUnstructured().WithMetadata().WithStatus().Unstructured, expectedErr: false, expectedRes: NewTestUnstructured().WithMetadata().Unstructured, @@ -2833,7 +2866,7 @@ func TestResetMetadataAndStatus(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - res, err := resetMetadataAndStatus(test.obj) + res, err := resetStatus(test.obj) if assert.Equal(t, test.expectedErr, err != nil) { assert.Equal(t, test.expectedRes, res) diff --git a/pkg/test/fake_dynamic.go b/pkg/test/fake_dynamic.go index 2a90323d4..df2b2f6e2 100644 --- a/pkg/test/fake_dynamic.go +++ b/pkg/test/fake_dynamic.go @@ -72,3 +72,8 @@ func (c *FakeDynamicClient) Delete(name string, opts metav1.DeleteOptions) error args := c.Called(name, opts) return args.Error(1) } + +func (c *FakeDynamicClient) UpdateStatus(obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) { + args := c.Called(obj, opts) + return args.Get(0).(*unstructured.Unstructured), args.Error(1) +} From 278bee12699304c7e1763739e66b0fd9fcfae6b4 Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Mon, 28 Mar 2022 14:58:25 -0300 Subject: [PATCH 07/28] Update codegen Signed-off-by: Rafael Leal --- config/crd/v1/bases/velero.io_restores.yaml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/config/crd/v1/bases/velero.io_restores.yaml b/config/crd/v1/bases/velero.io_restores.yaml index 68d1aefb0..4bc98b3a4 100644 --- a/config/crd/v1/bases/velero.io_restores.yaml +++ b/config/crd/v1/bases/velero.io_restores.yaml @@ -1773,6 +1773,26 @@ spec: PVs from snapshot (via the cloudprovider). nullable: true type: boolean + restoreStatus: + description: RestoreStatus specifies which resources we should restore + the status field. If nil, no objects are included. Optional. + nullable: true + properties: + excludedResources: + description: ExcludedResources specifies the resources to which + will not restore the status. + items: + type: string + nullable: true + type: array + includedResources: + description: IncludedResources specifies the resources to which + will restore the status. If empty, it applies to all resources. + items: + type: string + nullable: true + type: array + type: object scheduleName: description: ScheduleName is the unique name of the Velero schedule to restore from. If specified, and BackupName is empty, Velero will From 7f229747190be16e6b598a9174336b54a0960013 Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Thu, 12 May 2022 11:59:49 -0300 Subject: [PATCH 08/28] Update CRDs Signed-off-by: Rafael Leal --- pkg/apis/velero/v1/zz_generated.deepcopy.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/apis/velero/v1/zz_generated.deepcopy.go b/pkg/apis/velero/v1/zz_generated.deepcopy.go index 8b3175700..c0a8f2c56 100644 --- a/pkg/apis/velero/v1/zz_generated.deepcopy.go +++ b/pkg/apis/velero/v1/zz_generated.deepcopy.go @@ -1352,7 +1352,6 @@ func (in *RestoreStatusSpec) DeepCopyInto(out *RestoreStatusSpec) { *out = make([]string, len(*in)) copy(*out, *in) } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreStatusSpec. From 8ecc11fad269a682a8f2077949cb71beb1b8f3d3 Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Thu, 12 May 2022 12:00:34 -0300 Subject: [PATCH 09/28] Add restore status to cli Signed-off-by: Rafael Leal --- pkg/cmd/cli/restore/create.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/cmd/cli/restore/create.go b/pkg/cmd/cli/restore/create.go index caf94dc51..ac03246d4 100644 --- a/pkg/cmd/cli/restore/create.go +++ b/pkg/cmd/cli/restore/create.go @@ -85,6 +85,8 @@ type CreateOptions struct { ExistingResourcePolicy string IncludeResources flag.StringArray ExcludeResources flag.StringArray + StatusIncludeResources flag.StringArray + StatusExcludeResources flag.StringArray NamespaceMappings flag.Map Selector flag.LabelSelector IncludeClusterResources flag.OptionalBool @@ -115,6 +117,8 @@ func (o *CreateOptions) BindFlags(flags *pflag.FlagSet) { flags.Var(&o.IncludeResources, "include-resources", "Resources to include in the restore, formatted as resource.group, such as storageclasses.storage.k8s.io (use '*' for all resources).") flags.Var(&o.ExcludeResources, "exclude-resources", "Resources to exclude from the restore, formatted as resource.group, such as storageclasses.storage.k8s.io.") flags.StringVar(&o.ExistingResourcePolicy, "existing-resource-policy", "", "Restore Policy to be used during the restore workflow, can be - none or update") + flags.Var(&o.StatusIncludeResources, "status-include-resources", "Resources to include in the restore status, formatted as resource.group, such as storageclasses.storage.k8s.io.") + flags.Var(&o.StatusExcludeResources, "status-exclude-resources", "Resources to exclude from the restore status, formatted as resource.group, such as storageclasses.storage.k8s.io.") flags.VarP(&o.Selector, "selector", "l", "Only restore resources matching this label selector.") f := flags.VarPF(&o.RestoreVolumes, "restore-volumes", "", "Whether to restore volumes from snapshots.") // this allows the user to just specify "--restore-volumes" as shorthand for "--restore-volumes=true" @@ -279,6 +283,13 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { }, } + if len([]string(o.StatusIncludeResources)) > 0 { + restore.Spec.RestoreStatus = &api.RestoreStatusSpec{ + IncludedResources: o.StatusIncludeResources, + ExcludedResources: o.StatusExcludeResources, + } + } + if printed, err := output.PrintWithFormat(c, restore); printed || err != nil { return err } From 206709b978c2e9ba298fbd27dd47505c598d3eed Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Thu, 12 May 2022 11:35:11 -0300 Subject: [PATCH 10/28] Cleanup Signed-off-by: Rafael Leal --- pkg/restore/restore.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index 835b393bb..0c3f422a8 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -1256,7 +1256,6 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso addRestoreLabels(obj, ctx.restore.Name, ctx.restore.Spec.BackupName) // Clear out status. - objWithoutStatus := obj.DeepCopy() if objWithoutStatus, err = resetStatus(objWithoutStatus); err != nil { errs.Add(namespace, err) From d85ed612cb3df7dfea101db0638223275f8e4ba4 Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Thu, 12 May 2022 11:55:50 -0300 Subject: [PATCH 11/28] Cleanup Signed-off-by: Rafael Leal --- pkg/restore/restore.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index 0c3f422a8..8fdc014da 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -1137,14 +1137,6 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso shouldRestoreStatus := ctx.resourceStatusIncludesExcludes.ShouldInclude(groupResource.String()) ctx.log.Infof("restore status includes excludes: %+v", ctx.resourceStatusIncludesExcludes) - // Clear out status. - if !shouldRestoreStatus { - ctx.log.Infof("Resetting status for obj %s/%s", obj.GetKind(), obj.GetName()) - if obj, err = resetStatus(obj); err != nil { - errs.Add(namespace, err) - return warnings, errs - } - } for _, action := range ctx.getApplicableActions(groupResource, namespace) { if !action.Selector.Matches(labels.Set(obj.GetLabels())) { From 8f31bff1b53be3056e16da23ecf99cc73f2b68ee Mon Sep 17 00:00:00 2001 From: Abigail McCarthy Date: Fri, 13 May 2022 12:37:58 -0400 Subject: [PATCH 12/28] Add note about restoring when resource scaled to 0 Signed-off-by: Abigail McCarthy --- site/content/docs/main/restic.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/site/content/docs/main/restic.md b/site/content/docs/main/restic.md index ac75f0f9d..8fa1dd8b3 100644 --- a/site/content/docs/main/restic.md +++ b/site/content/docs/main/restic.md @@ -248,7 +248,7 @@ Instructions to back up using this approach are as follows: ### Using opt-in pod volume backup -Velero, by default, uses this approach to discover pod volumes that need to be backed up using Restic, where every pod containing a volume to be backed up using Restic must be annotated with the volume's name. +Velero, by default, uses this approach to discover pod volumes that need to be backed up using Restic. Every pod containing a volume to be backed up using Restic must be annotated with the volume's name using the `backup.velero.io/backup-volumes` annotation. Instructions to back up using this approach are as follows: @@ -412,7 +412,7 @@ data: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsUser: 1001 - runAsGroup: 999 + runAsGroup: 999 ``` @@ -524,6 +524,8 @@ within each restored volume, under `.velero`, whose name is the UID of the Veler 1. Once all such files are found, the init container's process terminates successfully and the pod moves on to running other init containers/the main containers. +Velero won't restore a resource if a that resource is scaled to 0 and already exists in the cluster. If Velero restored the requested pods in this scenario, the Kubernetes reconciliation loops that manage resources would delete the running pods because its scaled to be 0. Velero will be able to restore once the resources is scaled up, and the pods are created and remain running. + ## 3rd party controllers ### Monitor backup annotation From 1537bf5d62872654205e47985af3fe0090d489b6 Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Fri, 13 May 2022 15:36:03 -0300 Subject: [PATCH 13/28] Update CRD Signed-off-by: Rafael Leal --- config/crd/v1/crds/crds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/crd/v1/crds/crds.go b/config/crd/v1/crds/crds.go index 6ead09027..314c400b8 100644 --- a/config/crd/v1/crds/crds.go +++ b/config/crd/v1/crds/crds.go @@ -36,7 +36,7 @@ var rawCRDs = [][]byte{ []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4YKs#\xb7\x11\xbe\xf3Wt\xad\x0f\x8a\xab\x96C\xdbI%)\xdev\xa58\xa5\xc4֪č.[{\x00\a\xcd!\xac\x19\x00\x010\xe42.\xff\xf7T\xe31\x9c\aHJ\xaa\xac3\x17\x89x4>4\xfa\xf150\x9b\xcf\xe73\xa6\xc5#\x1a+\x94\\\x02\xd3\x02\xbf8\x94\xf4\xcb\x16O\u007f\xb5\x85P\x8b\xdd\xf7\xb3'!\xf9\x12\xae[\xebT\xf3\x80V\xb5\xa6\xc4\x1b\xdc\b)\x9cPr֠c\x9c9\xb6\x9c\x010)\x95c\xd4l\xe9'@\xa9\xa43\xaa\xae\xd1\xcc+\x94\xc5S\xbb\xc6u+j\x8e\xc6\vOK\xef\xbe+\xfeR|7\x03(\r\xfa\xe9\x1fE\x83ֱF/A\xb6u=\x03\x90\xac\xc1%h\xc5w\xaan\x1b\\\xb3\xf2\xa9ն\xd8a\x8dF\x15Bͬƒ\x16\xad\x8cj\xf5\x12\x8e\x1dan\x04\x146s\xaf\xf8\xa3\x17\xf3ދ\xf1=\xb5\xb0\ue7f9ޟ\x84u~\x84\xae[\xc3\xea)\b\xdfi\x85\xacښ\x99I\xf7\f\xc0\x96J\xe3\x12\xee\b\x86f%\xf2\x19@ܻ\x875\aƹ\xd7&\xab\uf350\x0e\xcd5IHZ\x9c\x03G[\x1a\xa1\x9d\xd7ֽ\xe2\x10\x00B@\b\xd61\xd7Z\xb0m\xb9\x05f\xe1\x0e\xf7\x8b[yoTe\xd0\x06x\x00\xbfX%\xef\x99\xdb.\xa1\b\xc3\v\xbde\x16coP\xef\xcaw\xc4&w \xd0\xd6\x19!\xab\x1c\f:#\xd8oQ\x82\xdb\n\va\xb7\xb0g\x96\xe0\x18\xe7w\x99_\xd8\xf7wG<@pM\x06\xd0M\r\x108s\x98\x03\xd0\xe9\x13\xd4\x06\xdc\x16I\xf3\xde☐BV\xbe)\x9c\x048\x05k\xf4\x10\x91C\xab3\xc84\x96\x85V\xbc\x90I\xe8\x00\xd6ݨ\xf5\x92nh\xfc\xff\x1a\xd5\x00н⯀\xf2\xa2u\xc3\xe0\xc1\xaa\x8f\xfd\xa6K\v?\xa0u\xa2\x04\x83ZY\xe1\x949\x80\xe0(\x9d\xd8\b4\xb0Q\xa6o6' \xd0\xdc\xdbn\xd2\x00J\x94\xfe\x80Z\xbdB\x11\xd1oVN\x19V!\xfc\xa4J\x1fvȜ\r\x0e\xec\xd9nU[sX\xa7]\x03X\xa7Lָ\tq\x98\x15\xe5&\xb1#\x1f\x1b\xaey\x1a}Ov\n\xb2\xc5$@\x0ed\xbf\xab0\xef9\xa1{\xf7}\bU\xe5\x16\x1b\xb6\x8c#\x95F\xf9\xee\xfe\xf6\xf1\x8f\xabA3\x806J\xa3q\"\x85\xce\xf0\xf52F\xaf\x15\x86\xaa\xbe\"\x81a\x14pJ\x15h\x83\xfd\x856\xe4\x11C8\x0ea\xc9H\fZ\x94\xae\xaf\x92\xf4\xa9\r0\tj\xfd\v\x96\xae\x80\x15\x1a\x12\x93\x0e\xa6Tr\x87Ɓ\xc1RUR\xfc\xa7\x93m\xc9\xcciњ9\x8c\x11\xfc\xf8\xf9 +Y\r;V\xb7\xf8\x16\x98\xe4а\x03\x18\xa4U\xa0\x95=y~\x88-\xe0ge\x10\x84ܨ%l\x9d\xd3v\xb9XT¥LY\xaa\xa6i\xa5p\x87\x85Ozb\xdd:e\xec\x82\xe3\x0e\xeb\x85\x15՜\x99r+\x1c\x96\xae5\xb8`Z\xcc=t\xe9\xb3e\xd1\xf0oḼ\xf6j\x80ub\x18\xe1\xf3\x89\xec\xcc\tP*\x03a\x81ũa\x17GE\xa7P\xf4\xf0\xb7\xd5GHK\xfb\xc3\x18k\xdf\xeb\xfd8\xd1\x1e\x8f\x80\x14&\xe4\x06\xa3+o\x8cj\xbcL\x94\\+!\x9d\xffQ\xd6\x02\xe5X\xfd\xb6]7\xc2ѹ\xff\xbbE\xeb\xe8\xac\n\xb8\xf6\xf4\x81BS\xab\xc9ry\x01\xb7\x12\xaeY\x83\xf55\xb3\xf8\xd5\x0f\x804m\xe7\xa4\xd8\xe7\x1dA\x9f\xf9\x8c\a\a\xad\xf5:\x12=9q^#α\xd2X\xd2\xe9\x91\x02i\xa6؈\x18\xa1(p\xb2\xf1\xf0b 8\xef\xb8\xf4e\xa3\xd3x\xd0\b\xd9\xfbܜ\x84M\xf6bj\n\x98a\xe4D(@=\x8e\xb2d\x8e\x93\x1cac\x80-&\x12N\x1c\x03}Rq\xbc\xb0\x8f;\xc51\a\x9b\xa6\x82۲`\xadĭ(\x1e\xb5RNW\xa1O\xc9\x17\x01ӊ_\xc0\x15Wd`p\x83\x06e\x89)p\x9d#\x0e\x19d\xfd\x94>\xc5x\xda(\xe0LT\xcf\"~w\u007f\x9b\"yRb\xc4\xee\xa6\xeb^\xd0\x0f}\x1b\x815\xf7\x89\xee\xf2\xdaW\xb7\x9b\xb0\x98\x8fiN\x01\x03-0P\xc0.I\x80\x90\xd6!\xe3\xa06Y\x89T\xa8\x009\xbe\xc18\xe3m\x88`1T\x1eS\v\xe9\x1e\x18\xc5N\xc1\xe1\x1f\xab\x0fw\x8b\xbf\xe7T\xdf\xed\x02XY\xa2\xf5\f\xd8a\x83ҽ\xedH9G+\fr\xa2\xd8X4L\x8a\rZW\xc45\xd0\xd8O?|\xcek\x0f\xe0Ge\x00\xbf\xb0F\xd7\xf8\x16D\xd0x\x17\x96\x93\xd1\b\x1b\xd4\xd1I\x84\xbdp[1N\xa6\x9d\x06ȼ\xe2\xb6\xf7~\xbb\x8e=!\xa8\xb8\xdd\x16\xa1\x16O\xb8\x847\x9e\xd6\x1ca\xfeJ\xbe\xf3ۛ\x13R\xff\x10\\\xfb\r\rz\x13\xc0uy\xb8\xeftG\x90\xc1\xf3\x8c\xa8*<\xb2\xaa\xf1\xe7\x93\n\x85\xeaoA\x19ҀT=\x11^0\x9d^\b\x94\xc8'\xa0?\xfd\xf0\xf9$⡾@H\x8e_\xe0\a\x10\xb1\xacъ\u007f[\xc0Go\x1d\a\xe9\xd8\x17Z\xa9\xdc*\x8b\xa74\xabd}\xa0=o\xd9\x0e\xc1**\x92\xb0\xae\xe7\x81\aqس\x03i!\x1d\x1c\xd9\x1b\x03͌;k\xad\x89\xfd|\xfcp\xf3a\x19\x90\x91AU>\x12S\xd6\xdc\bb3DcB.\xf6\xd68I\xe6\xe9\xb3m0\x1f\xa7\xa0\xdc2Ya\xd8/¦\xa5\xecX\\\xbdƏ\xa7\x94$}\x19j2\x0e\x1c\xff\xb7\xe4\xfe\xcc\xcdy\x06\xfd\x8c\xcd\xf5\xab\x8c\xb3\x9b{j\xd7h$:\xf4\xfb㪴\xb4\xb5\x12\xb5\xb3\v\xb5C\xb3\x13\xb8_\xec\x95y\x12\xb2\x9a\x93i\u0383\r\u0605/Q\x17\xdf\xf8?\xafދ\xaff\x9f\xbb\xa1A\x95\xfd5wE\xeb\xd8ū6\x958\xec\xf3\xf3\xd8\xd5*2\xab\xf1\\r\x8b\xfdV\x94\xdbT\x9c\xc4\x18{\u0099\x041a\x1eB3\x93\x87\xafnʤ\xd0\xd6\x10\xa2\xc3<^\xb0͙\xe4\xf4\xbf\x15\xd6Q\xfb\xab4؊g\xb9\xef\xbfno~\x1f\x03oū|\xf5\x04\x01\x0f6ҿO\xb8@\xcc\x1e\x06\x83\x13u\xcc0\xd6n̋\x98\xa1cU\x86\x8a\xf5/\x02\xcf\x11\xb6\xb3\x1a\x18^ӱ\xca\x023\b\f\x1a\xa6\xe9\xe4\x9e\xf00\x0f)^3A\xf9\x99Rpw\xcf\x01L\xebZdSqL䑄F\xbeO\x856\xab쩽g\xcf!H\xb8\xa0\xffxř\xa1\xec\x11@\xe07\x1dm\xf7\xb7Z9^|\x9a\x14\x9f\xd4\"ե\xc4ֆ\x10\xe7\xf9\x02j4\x86\n\x8aQ\x93V|Ԓ\xbd\xd9J\x9d\x83\x9b\xb7\xb3\xca\f\x17\xaa/\xa8+\xc3Eq\xd4i\x88\".]\x1f\x13\x85~meY*b\xa7ë\xfb\xf3\xc7{=\x9d\xe1/q\f\x0f\xe0\x9ch\xc8f{\xd7\xcaq\x8d\\i\b=qa\xa6\x8f\xdb$\r\xb9\xa7\x8e\xc4l7L\xd4\xc8!\xbd\x1d\x8c\xe7d\xa4\xf6\xa5\xacqCA\xaeյb<\x15d\x11^GϨ^\xf7\xb7#W\xf6\x8c\xcc\xd6\"\xf7\x95|F\tSʶQ\xa6a.\xdc\xe6ͳBe[\xd7l]\xe3\x12\x9ci\xa7\xddg\x82E\x83ֲ\xea\x92+\xfe\x1cF\x85:5N\x01\xb6V\xad\xeb\n\xd5AP\xb8\xb2Ѧ^V+gK\xc0\xa193\xa2\xe86Rպ\xf6s\xfa\x81\xe0\xf8\xe0\xe4Q\xad1\x9f\xea^\x13\x13\x00\xfc\x83\xc9%\x844&\xe7`]\xf4:\xeba\xf4\xa1l\x9b\xe9*s\xb8\xc3}\xa6u\xf2\xd0\xd3\xef\xbcN.\x93\xe9\xfb\xd1{Ë\xf6\x1f\x17\xba\xa4\x828\f\xb6\xaaNά\x1c\xabA\xb6\xcd\x1a\r\xe9a}ph\x87\xe1n\xe6r\xd0\n53\xe4\xe9\xfe&\xfcz\xfcT\xf3\x16\xac\xf0\xd7{ķ\x02\x01\vŷ\xa5\xe4D\xc4R\x19̄L\x98\xa6\x95A\x12\x19\xc2\xff=\xf3G\xd6N&\x8d\x1e9\xefɎW\xc4\xfd\x96v\xdd=\u007f\xa4Ê\xdc\x06~\xfdmv\xa49\xac\xa4\x02\x02\xf9\xdd\xf8I\xffM\xb8\xe0Io\xf4\xfeg\xa9d`\xd3v\t\x9f>\xcf\xd2\xd3\xddczz\xa7\xc6\xff\x06\x00\x00\xff\xff\xb6\xe8a\xa8\a!\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4Y[s\x1b\xb7\x15~\xe7\xaf8\xe3<\xa8\x991\x97\x89\xdbi;|\xb3\xa5\xa6\xa36\x915\xa6\xaa\x17\x8f\x1f\xc0\xc5\xe1.\xa2]`\x8b\x83%\xcdf\xf2\xdf;\a\x17ro\x14%M\x94\xec\x8b-\\\x0e>|8w\xce\xe6\xf3\xf9L4\xea\x1e-)\xa3\x97 \x1a\x85_\x1dj\xfe\x8b\xb2\x87\xbfS\xa6\xccb\xfb\xfd\xecAi\xb9\x84˖\x9c\xa9?!\x99\xd6\xe6x\x85\x1b\xa5\x95SF\xcfjtB\n'\x963\x00\xa1\xb5q\x82\x87\x89\xff\x04ȍv\xd6T\x15\xday\x81:{h\u05f8nU%\xd1z\xe1\xe9\xe8\xedw\xd9߲\xeff\x00\xb9E\xbf\xfdN\xd5HN\xd4\xcd\x12t[U3\x00-j\\Bc\xe4\xd6Tm\x8d\x16\xc9\x19\x8b\x94m\xb1Bk2ef\xd4`Χ\x16ִ\xcd\x12\x8e\x13asD\x14nsk佗\xf3)\xc8\xf1S\x95\"\xf7\xef\xc9\xe9\x1f\x159\xbf\xa4\xa9Z+\xaa\t\x1c~\x96\x94.\xdaJ\xd8\xf1\xfc\f\x80r\xd3\xe0\x12n\x18J#r\x943\x80H\x80\x876\a!\xa5\xa7TT\xb7Vi\x87\xf6\x92E$*\xe7 \x91r\xab\x1a\xe7);\xc8\x01\xb3\x01W\"\x1f\xe9\xe9\x16J+]\xf8\xa1\x00\x01\x9c\x815BD\"\xbd0\x80\x9f\xc9\xe8[\xe1\xca%dL\\\xd6\x18\x99\xe9$3\xae\t\x9c\xdf\fFݞ\xefA\xce*]\x9cB\xf6\x1b\x83\xea\xe1\xb95\xf2\x05H\x9eslX\xdb;\xf4\xbe;t\xee\xdc[#\xe3\x06\x88\n\x04\xe4\x84k\t\xa8\xcdK\x10\x047\xb8[\\\xeb[k\n\x8bD\x130\xfc\xf2\xac)\x05\xf5q\xac\xfc\xc4\xeb\xe2\xd8\x18[\v\xb7\x04\xa5\xdd_\xffr\x1a[ܔ9\xe3D\xf5a\xef\x90zH\xef\x86\xc3\x01-+v\x81\xf6\x8f\x83\xbbfHWF\xf7y\xfd0\x18\x9d\x02\xdb\x11\x9a\x9c^6rX=\xa9\uf2fe<)\\\x18\b\xd3\xdb\xef\x83\xdb\xc8K\xac\xc52\xae4\r\xea\xf7\xb7\xd7\xf7\u007f^\xf5\x86\x01\x1ak\x1a\xb4N%O\x16\xbe\x8e\a\xef\x8cB\x9f\xd9\v\x16\x18V\x81d\u05cd\x14\x8c\"\x8c\xa1\x8c\x18\x82\xb1(\x02\x8b\x8dEB\x1d\x9cyO0\xf0\"\xa1\xc1\xac\u007f\xc6\xdce\xb0B\xcbb\x80J\xd3V\xdeڷh\x1dX\xccM\xa1\xd5\xff\x0e\xb2\x89m\x8f\x0f\xad\x84\xc3\xe8N\x8f\x9f\xf7wZT\xb0\x15U\x8boAh\t\xb5\u0603E>\x05Zݑ\xe7\x97P\x06?\xb1\x86(\xbd1K(\x9dkh\xb9X\x14ʥȕ\x9b\xban\xb5r\xfb\x85\x0fBj\xdd:ci!q\x8bՂT1\x176/\x95\xc3ܵ\x16\x17\xa2Qs\x0f]\xfb\xe8\x95\xd5\xf2\x1b\x1bc\x1d]\xf4\xb0\x8e\x8c.|>\xae<\xf2\x02\x1cX@\x11\x88\xb85\xdc\xe2Htr\x8f\x9f\xfe\xb1\xba\x83t\xb4\u007f\x8c!\xfb\x9e\xf7\xe3F:>\x01\x13\xa6\xf4\x06mxč5\xb5\x97\x89Z6Fi\xe7\xff\xc8+\x85zH?\xb5\xebZ9~\xf7\xff\xb6H\x8e\xdf*\x83K\x1f\xce\xd9_\xb6\rk\xae\xcc\xe0Zå\xa8\xb1\xba\x14\x84\xaf\xfe\x00\xcc4͙ا=A7\x13\x19.\x0e\xacu&R\xb6p⽆\x19\xc0\xaa\xc1\x9c\x9f\x8f\x19\xe4\xadj\xa3ro\x1b\xec~@\x8c\xd6g=\xd1Ӧ\xcb\xdfZ\xe4\x0fm\xb3rƊ\x02\u007f4A\xe6p\xd1\x00ۇ\xa9=\t\x9c\xeeļ \x1c(\xac\x1c\t\x05\xa8\xd2\xe6]\x89\x16\xfd\x1e\x0e\x8d*g\xf52\xa4\x9c\xb1{\x16\x1c\xa2e6\x92p\xe2!\xfc\x95\x8d\xde,\xfe9\xc5\xfc\xe1\x16 \xf2\x1c\x89|\xbc\xc6\x1a\xb5{{\x88\xd9\x12IY\x94\x9c\xb8`V\v\xad6H.\x8bg\xa0\xa5\xcf\xef\xbeL\xb3\a\xf0\x83\xb1\x80_E\xddT\xf8\x16T`\xfc\xe0\xfe\x92\xce(\nt\x1c$\xc2N\xb9R\r\x83ց\x01֮x흿\xae\x13\x0f\b&^\xb7E\xa8\xd4\x03.\xe1\x8d\xcf\x04\x8f0\u007fa\xc3\xfa\xf5\xcd\t\xa9\u007f\n\x06\xf4\x86\x17\xbd\t\xe0\x0e\xf1\xaek\x91G\x90\xae\x14\x0e\x9cUE\x81\xc7Dt\xf8y\xe7\xcd.\xf1[0\x96\x19Ц#\xc2\v\xe6\xd7\v\xfe\b\xe5\b\xf4\xe7w_N\"\xee\xf3\x05JK\xfc\n\xef@\xe9\xc0Mc\xe4\xb7\x19\xdcy\xed\xd8k'\xbe\xf2Iyi\bO1kt\xb5\xe7;\x97b\x8b@\xa6F\xd8aU\xcdC\xbe!a'\xf6\xccBz8\xd67\x01\x8d\xb0\xeeQmMY\xc6\xddǫ\x8fˀ\x8c\x15\xaa\xf0\xfe\x8e\xa3\xd3Fq\xd6\xc0\xe9B\x88y^\x1bGA3}\xd4\x06\xf5q\x06\xf2R\xe8\x02\xc3}\x116-G\xa1\xec\xe2%v<\x0e\xfd\xe9\x9bH\x01\x86\x8e\xe3\x0f\v\xa2O\xbc\x9c\xcfT\x9fp\xb9n\xad\xf5\xe8\xe5\x1e\xda5Z\x8d\x0e\xfd\xfd\xa4ɉ\xaf\x96c\xe3ha\xb6h\xb7\nw\x8b\x9d\xb1\x0fJ\x17sV\xcdy\xd0\x01Z\xf8\xf2t\xf1\x8d\xff\xe7\xc5w\xf1\x95\xecS/\xd4+\xb0_\xf3V|\x0e-^t\xa9\x94+>=\x8e]\xacb\x023\xdc\xcbf\xb1+U^\xa6\" \xfa\xd8\x13Ƥ8\xe3\x94\xc15\v\xbd\u007fuUfB[ˈ\xf6\xf3\xd8X\x9a\v-\xf9\xff\xa4\xc8\xf1\xf8\x8b\x18lՓ\xcc\xf7?\xd7W\xbf\x8f\x82\xb7\xeaE\xb6z\"\xd1\r:Ҙk\xc9Tn\x14\xda3y٧\xde\xe2\x94WN䅇5\xcfJ\fI\x8b\x86J㮯\xce\xe0X\x1d\x16&\f\xc7\a\x88\xe9`\x925h\xeb<\vO\x10u\x06KlKL\xe4\xd8\x11I\xc89\xfc\b\xe7\xb5\x1eϴ\xb1>\x17!\x97d\x9c@\xf5\x11Χ+\x87\xc1\x9a\xc6\xc8\xc1H_\x13\x06\x93ǧ\x19L\xf4\x1ab]\xbc\xe3\xb2\xcaw[\x9eSX\x85\x0eOd6طK}\x1fNn_\\Z\xe5\x86\x13\xc7~7\xf9\xf1W\xbe\x1c\xef\xf0}\f+\x03:\xa7j\xf4\xf5JhN\xed\x04\xa5C\xa6^\x14:\xf2\xc2V\xefSY\x1cJ\x9f\xd6qֹ\x11\xaaB\t\x87~6\xdcq\x85\xe9\v\xfa\x8b\xa9,&\tj\t\xa5\xaf='@\x8f\xf7\xa5\x1e\x19\x97\xf1s\x161Z\xa1۪\x12\xeb\n\x97\xe0l;\x9e~Āj$\x12\xc59\v\xfa)\xac\n\x15_\xdc\x02bmZw(\xf9\xa2)E*.(j\xc1\xf3\xca\xceR\xd09(\xb7\xbcfJ\xe3\x0eF\xfd\xb8\xca\U00047ead\xc7\xc7\xcc\xe1\x06w\x13\xa3\xa3\x9eew\xf22\xa9\xd0\xc4\xdc\x0f^;\x9eE@<\xe8\x1c\aq\x19\x94\xa6J\xdam\x9c\xa8@\xb7\xf5\x1a-\x13\xe1\x1b\xa5\x89\x91\xe4\x1a\xa6jh\x9f{\x1f\x99j\x92\xa8ѠG.;\xb2c߬;Ү\x0f]\xe1Dj\x8cx\xf0˯\xb3c\xf0\x139\xe7{(o\x86?<\xbe\t\xf5x\xfa\x1d\xd1\xff\x99\x1b\x1d~\xf8\xa3%|\xfe2\x83\xd8n\xbbO?\x0e\xf2\xe0\xff\x03\x00\x00\xff\xff\x8c\x89\xe8@\xae\x1d\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4WMo\xdc6\x13\xbe\xef\xaf\x18\xe4=\xe4\xf2J\x9b\xa0\x87\x16\xba\xa5n\v\x04\x8d\rc\x1d\xf8R\xf40\"gw\x19S$K\x0e\xd7\xdd\x16\xfd\xef\x05Iɫ\x95do\x1c\xa0\xbaq8\x9c\x8f\xe7\x99\x19R\xab\xaa\xaaV\xe8\xd4=\xf9\xa0\xaci\x00\x9d\xa2?\x99LZ\x85\xfa\xe1\x87P+\xbb>\xbc_=(#\x1b\xb8\x8a\x81m\xb7\xa1`\xa3\x17\xf4\x13m\x95Q\xac\xacYu\xc4(\x91\xb1Y\x01\xa01\x961\x89CZ\x02\bk\xd8[\xad\xc9W;2\xf5Cl\xa9\x8dJK\xf2\xd9\xf8\xe0\xfa\xf0\xae\xfe\xbe~\xb7\x02\x10\x9e\xf2\xf1Ϫ\xa3\xc0ع\x06L\xd4z\x05`\xb0\xa3\x06<\x05V\u0093\xb3A\xb1\xf5\x8aB} M\xde\xd6ʮ\x82#\x91\xdc\uef0d\xae\x81\xd3F9݇T\xd2\xd9dC\x9b\xc1\xd01oi\x15\xf8\xd7\xc5\xedO*pVq:z\xd4K\x81\xe4\xed\xa0\xcc.j\xf43\x85\xe4 \b먁\x9b\x14\x8bCAr\x05\xd0C\x90c\xab\x00\xa5̠\xa2\xbe\xf5\xca0\xf9+\xabc7\x80Y\xc1\x97`\xcd-\xf2\xbe\x81z\x80\xbd\x9eA\x96u\a\xc0>\xec\xa8_\xf319\x97\xc8EP\xb6\x0f\xefK\xd8bO\x1d6\xbd\xa6ud>\xdc~\xbc\xff\xee\xeeL\f\xe0\xbcu\xe4Y\rP\x96oTC#)\x80\xa4 \xbcr\x9c\x19~\x9b\f\x16-\x90\xa9x(\x00\xefiȟd\x1f\x03\xd8-\xf0^\x05\xf0\xe4<\x052\xa5\x9c\xce\fCRB\x03\xb6\xfdB\x82k\xb8#\x9f\xcc@\xd8ۨe\xaa\xb9\x03y\x06O\xc2\xee\x8c\xfa\xeb\xc9v\x00\xb6٩F\xa6\x9e\xcfӗ\xf16\xa8\xe1\x80:\xd2\xff\x01\x8d\x84\x0e\x8f\xe0)y\x81hF\xf6\xb2J\xa8\xe1\xdaz\x02e\xb6\xb6\x81=\xb3\v\xcdz\xbdS<\xf4\x8e\xb0]\x17\x8d\xe2\xe3:\xb7\x81j#[\x1f֒\x0e\xa4\xd7A\xed*\xf4b\xaf\x98\x04GOkt\xaaʡ\x9b\xdc?u'\xff\xe7\xfbn\vo\xcfb-L\x06\xf6\xca\xecF\x1b\xb9\xb0_` U6\xa8\x00\xd8\x1f-Y\x9c\x80N\xa2\x84\xce\xe6\xe7\xbb\xcf0\xb8\xcedL\xd1ϸ\x9f\x0e\x86\x13\x05\t0e\xb6\xe4\v\x89[o\xbbl\x93\x8ctV\x19\xce\v\xa1\x15\x99)\xfc!\xb6\x9d\xe2\xc4\xfb\x1f\x91\x02'\xaej\xb8\xca\x03\x05Z\x82\xe8R\xe5\xca\x1a>\x1a\xb8\u008e\xf4\x15\x06\xfa\xcf\tHH\x87*\x01\xfbu\x14\x8cg\xe1T\xb9\xa06\xda\x18\xc6\xd53|MGН#\x91\xe8K\b\xa6\xa3j\xabD\xee\r\xd8Z\x0f8ӯ\xcfL/\xb7n\xfaZ\x14\x0f\xd1ݱ\xf5\xb8\xa3O\xb6\u061c*Mb\xfbq\xe9\xcc\x10\\\x9a,\xa5\x8diYqf\x1b\x80\xf7ȣ\xfeeT\xe6i\f,\xe6\xf3\x02\t\x99\bL\xedl\xd0\b\xfa%W\x94\x11\xc7\v9]/\x1cI)\xed\xed#\xd8-\x93\x19\x1b\xedc]Ȥ%\xf0Ѽ*\xd8rU|\x94\xa9\xf0\xb6\x8a\xfc\x85@7\x13\xf5\x01\xf7mԺ\xb7U\t\xdb9d\xd5jZv\x99\xbeT6\xaaX9\x96\xde\xffv\xbc\x0f鞢\xa7\x9b\xedB\x06\xf7\xe7\xda\xe3\xc2)\x82>\x94\x94\n\xf8\xf3;\xfa\xfc\xebk%\x80\xb3\xb2\x0f\xa2/\xe8\x90\xf2{E\x0e\x89r\xe5i2A\xab\xe5\xf6\x98\xe8,U\xdbDe\xca\xf1d{\x82\xdfW\x8d\x0fF\x8e\xe15\x03$\x1f\x18\xc0\x16\xd1{2ܛ\xc97\xea7\x8f\x10\x8d\x81G\xed\x93^\"\x17*\xe0\xd3\xfc\xc4\x10X2\x06\x9c\x04\xe3~{\xc4\xe9-\x94I[괭\xf5\x1dry\xeaT\xc9\xd0L#=)\xb1\xd5\xd4\x00\xfb8\xdf~i\xaeP\b\xb8\xbb\x94\xddu\xd1*\x97m\u007f\x04\xb0\xb5\x91\x9f\x81\x9e\xf7\xf3(\xe0\x02\x1d\x17\"u{\f\x97\xe2\xbcM:K\x05\xf14\xbf/\x87@&vs7\x15\xdc\xd0\xe3\x82tC(\xe7}\\\xc1\x8d\xe5\xe5\xadg3\\슙0\xa4w\x89\x1c\xf1\x1cJ#\x8f%\xb1}zg\r\x89\xf4\xbd\x05\u007f\xff\xb3:\xb5\x19\nA\x8eI\xdeL\xff%\u07bc9\xfb5\xc8KaMyʇ\x06~\xfb}U\x1c\x93\xbc\x1f\x9e\xfbI\xf8o\x00\x00\x00\xff\xffW\xb1\xbaH\x82\r\x00\x00"), - []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec\xbd}s#\xb7\x910\xfe\xbf?\x05j\xe3\xfaI{\x11)or\xc9\xefn+\xf5\xa4\x94]\xd9Q٫U\xad\x94\xf5\x93r|>p\xa6I\xe24\x03L\x00\f%\xde\xf9\xbe\xfbSh\x00\xf3B\x0e\xc9\x01\x86\xda\x17{pU\x17/5\xd3\x034\x1a\xfd\x8enZ\xb0\xf7 \x15\x13\xfc%\xa1\x05\x83G\r\xdc\xfcKM\xef\xffMM\x998_\xbd\xf8\xe2\x9e\xf1\xf4%yU*-\xf2w\xa0D)\x13x\rsƙf\x82\u007f\x91\x83\xa6)\xd5\xf4\xe5\x17\x84P΅\xa6\xe6ge\xfeIH\"\xb8\x96\"\xcb@N\x16\xc0\xa7\xf7\xe5\ff%\xcbR\x90\b\xdc\u007fz\xf5\xd5\xf4\xff\x9f~\xf5\x05!\x89\x04|\xfd\x8e\xe5\xa04͋\x97\x84\x97Y\xf6\x05!\x9c\xe6\xf0\x92HPZHP\xd3\x15d Ŕ\x89/T\x01\x89\xf9\xd8B\x8a\xb2xI\xea?\xd8w\xdcD\xec\"\xde\xd9\xd7\xf1\x97\x8c)\xfdm\xf3\xd7\xef\x98\xd2\xf8\x97\"+%\xcd\xea\x8fᏊ\xf1E\x99QY\xfd\xfc\x05!*\x11\x05\xbc$\xd7\xe63\x05M \xfd\x82\x10\xb7&\xfc\xec\xc4\xcdz\xf5\u0082H\x96\x90S;\x1fBD\x01\xfc\xe2\xe6\xea\xfd\xefo[?\x13\x92\x82J$+4b\xc6͍0E(y\x8fk3\x13\xc0M zI5\x91PHP\xc0\xb5\"z\t\x84\x16E\xc6\x12Db\x05\x91\x101\xaf\xdeRd.E^C\x9b\xd1\xe4\xbe,\x88\x16\x84\x12M\xe5\x024\xf9\xb6\x9c\x81\xe4\xa0A\x91$+\x95\x069\xad`\x15R\x14 5\U000c8d63AG\x8d_7\xd6rb\x96k\x9f\"\xa9! \xb0Sv(\x83\xd4a\xc8\xccV/\x99\xaa\x97\xb6\xb9\x1c\xb7$ʉ\x98\xfd\x17$zJnA\x1a0D-E\x99\xa5\x86\xeeV \rr\x12\xb1\xe0\xec\xbf+\xd8\xca,\xd4|4\xa3\x1a\xdc~׃q\r\x92ӌ\xachV\xc2\x19\xa1<%9]\x13\t\xe6+\xa4\xe4\rx\xf8\x88\x9a\x927\xb8=|.^\x92\xa5օzy~\xbe`ڟ\x9fD\xe4yə^\x9f\xe3Q`\xb3R\v\xa9\xceSXAv\xae\xd8bBe\xb2d\x1a\x12]J8\xa7\x05\x9b\xe0\xd49\x9e\xa1i\x9e\xfe\xa6ڶ\x93\xd6\\\xf5\xdaP\x9eҒ\xf1E\xe3\x0fH\xe6{v\xc0\x10\xbc\xa5%\xfb\xaa]E\x8dh\xf3\x93\xc1λ\xcbۻ&\x9d1\xb5\x89}\xc4{\x83\xf8\xea-0\bc|\x0e\xd2n\"R\x9b\x81\t<-\x04\xe3\x1a\xff\x91d\f\xf8&\xfaU9˙6\xfb\xfe\xcf\x12\x94!h1%\xaf\x90\xa9\x90\x19\x90\xb2H\xa9\x86tJ\xae8yEs\xc8^Q\x05O\xbe\x01\x06\xd3jb\x10\xdbo\v\x9a\xfcp\xf3a\x8b\xb5\xc6\x1f<\xf3ڱ_\xee\xf4\xdf\x16\x90\xb4N\x8cy\x8d\xcd\xdd1's![\xcc\xc1\xbc2m\x01\xed>\xb4f\xd8\xd3o8\xd8\xe6_6\xa6\xf2\x97\xeaAC?f\x12%g\xff,\x01Y\x9c=\xb1\xb0\xc5R\xb6@\x12??$\x8b\xe9\xd6\xdfw\xe0\xd4\fxL\xb22\x85\xb4\xe2\xb6[k٘\xf1\xe5\xd6\v(\x8e(\xe3\x86\xfe\r\xfb7\xd3\xe6\xf5_\r;\xed\x981\x95@\f\x052n\xe1\x11\xc6q\xb1\x9d\x986\x83i\xc8;&\xb7wu\x04\xe5\x1c\x9de\xf0\x92hY\xc2\x0e\xccP)\xe9z\ab\xbcl\ue2d7\xeay\xc7\x102\x96@SPX\xd4X!C\xe5\xf6\x8c\xc8'\x8e\x15\xa6\f;\xf3\xab\xbc\x11\x19K\xd6\aQ\xd3\xf5\x92?n\xee\xf0y\n\x9e\xc1\x92\xae\x98(eǚ̑4\xcf\xdeג\xb4\xe6\xa6\xc203\a%\x8d[q'\xb6\x96B\xdc\x1f\xda\xfc\xbf\x9agj\xb6M\x12T\xeb\xfcZ\xa4\xdbn'Eg@\xe0\x11\x92RwL\x93\x90\xb4D\t\"$)\x84һ7~7\xf3!\x96\x1f\xec\xa2Z\xb2\x8fj\xb6V\xe6x\xa5\xdf:\xb3\xd0\x16\xdf\x14\x1c\xcc\\s\xb3u\xf5\xb3R\x94\xf6\xd9M\x01\xd7\xc0x7FȌ*H\x89pd_f\xa0ܷR\xdc\xfe\x9a\xb1\x9c\xed\x04]-ު\x1a\x19\x9dAF\x14d\x90h!\xb71\xd9\a\x9fv\xf4a\x96;\xf0\xd8\xc16\xdb\xf4_/l\x0fHb\xc8\xfcaɒ\xa5\xd5\x02\fm\"\x1c\x92\nP\xc89\x8c\xa6\xba\u07b5Hrh\xef\xddG\xf6\xf1\x8ez\x1c8S\x9b\xf0\xba\xf8I=z\xf0\xdbz\x1c\xe0\xbc[\x9c\xc5\xfd\xde):\xeb\xf1\xcbD\xac\x17%\x11D{\xb5\xf5\xeaq\x89\x16\xad*\xa3\xed_\xcd\t\xe4\x85^\x9f\x11\xa6\xfd\xaf\x87 \xd2,k|\xff3ޘp\x8a\xbf\xda|\xf3\xa8\x14\xbfwW\x0eA4\xbbR}\xfe3\xdc\x14\x14\x16\xb7NV\xf4ސ\xef\x9ao\x9d\x116\xaf6$=#s\x96i\x90\x1b;3\xe8\xbc\x1c\x03\x19}\xe4\x9d\x199\xd5\xc9\xf2\xf2\xd1h6\xaa\xf6@\xf5\xc4\xcb\xe6\xcbV'\xf6FB[0\x1f\x80K\xd0~e\x12rk\x17\xdf!6\xeb_Р\xb8\xb8~\r\xe9>\xf4\x90~\x94\xb7\xb5\x90\x8b\x8d\xc96?\xed\x14\xfd\xbe\xcbp\xaaOe4Y\x8f\xc7\x19\xa1\xe4\x1e\xd6Vc\xa1\x9c\x98͡\x1a\xf5\xddN\xf3i\x1b9\xe8z\xb1\xea1\xac\x11\x8c\xf3\xa5\x1c|\xbb/)\xd8q\x0f\x1d\xfa~\xd7h!\xd0\xcc\xc9Y\xb8\x16\x93\xe6\aD\x04Z\xde\xfd\x91G\xd0/\xe6y\xd1\xe1ő\xfe\x8c\xc4\x0f\x8f\xfb\x88eV\xdb\xd6\xf0\x1f\xe2ƞ(\xbbE\xe6\x14,Y\xd1s\xa1\xe8>T\x80\xa7\xc5{\xc6\xdeӌ\xa5Շ,\xdd_\xf1\xdd\xdap{\\\v}\xc5ϬI\xa6\x90J^\vP\xd7B\xe3/O\x82N;\xf1\bd\xda\x17\xf1xq˶\r\x1e\x9a.\xb6\x1e\xc4mǕ\xf5\xa4T\xdb\xc3\x14\xb9\xe2\xc6pq\xf8@\x87\xa9\xfd\xdc~\xf9\xd0\x1ey\xa9Ї\xc6\x05\x9f\xa0\xa8\x9cv}\xc9\"\xbb'H![;\xb2=\xb5\xea\xa3\xf6\x83=\xc1\xde\x19Ib߷.\xe0\x8c&\x90zk\x13\x1d\x97TÂ%$\a\xb9\xd8'8\x9a\xa30\xfc\xbd\xdf\x14zr];\x02)\xac\x9fh\xf7ñ\xee\xf4\xf0d&\xe6\xe4\xf6x\xcao\xf6\xc1Gw\xf8+w?zxE(bQ\xff8\x88]\x9a\xa6\x18\\\xa2\xd9M\x00\xc7\x0f؋m\xd9o'f%dN\vs~\xffLj9$\xe8\xff%\x05e\xb2\xc7\x19\xbe\xc08Q\x06\xadw\x9dg\xac\xf9\x19\xf3\x05\xa6\x88\xd9\xdf\x15Ͷ=\xe1\x1d\x8b\x13\x86\xb7@f\x05\xb9\x98oi,g\xe4a)\x94\x95\xa9s\x06Y\x97˦=\x98\"\xcf\xeea\xfd\xecl\x8b\x0f<\xbb\xe2Ϭ\x80\x0ff7\x95\xb6 x\xb6&\xcf\xf0\xddgC\x94\xa0\x9e\x94\xd8\xeb1\xde\xe9\xe7\xaeG\x8b,\x9a\xbe\xee\xda\xc9\xed\xd4\xdc}\xb3\xeeE\x87\x85P\xfa\xaf\xdd\x0e\xbb\x1d\xf3\xb9\xf1o\xb4u\xd3\x0e\xbf\xd7A\x9d\xdd\xf9\xb0*\xa6j4\xb9\xb9\x06\xe9\x9cx\x96\xd1z\v`\xa0mt\xc8IW9\xe8h\xe5Y5\b>@\x156\xe6\xd1g\x8a!Z\xa3\xc1K\xa0\xbe}\xf9\xd8\xf01\x9a\x13j\xfe\xdd\\ȱ\xb5\xdaD\xe49\u074c\xf2\xf5\x9a\xea+\xfb\xa6\xa7i\a\xc8\xee\xbe\\\x94x.\xfb\xab{\x9e\x860\xbe\xf7\xc0\xf4\x92qB\xfd\xf1\a\xe9\b\x8a\x92B\x1c\xe6Dv,\xa9\"3\x00^\xf9\xc6?\x05y\x9d3~\x85\x1f /\x8e.\xdfI\x8d\xae\xa8\xed\xf4\xa8\xae6\xb4\xfa\x01%N_\xd5H\xa4\xe4a\t\x12ZT\xb1\xed\xf06\x1acO\x90\\\xe8\xa6_\xc1\xc0-Dz\xa2ȜI\xa5\x9b\x13\xedKp\xa5\xeaK\x0e\x81;lVw\xc7r\x10\xa5\x8e\u0603\xcb\xfa\xedV\x806\xa7\x8f,/sBsQ\xf6\x10\xeev\x18\xf9\xc2\xf2*\x8a\xeav\xe0\x812]œ\xd0â\x85٥\"\x03\xddw\x8bg07\xec(\x11\\\xb1\x14\xa4\x8f\xf2\u06dde\xc2\x1c\xdc9eY\xd9\x15\xbe\xe9\x1a\xa1f*\xbf\x942\xcaJ}k\xdflx\r\x97⡍\xa0\xde(X\xd2\x15\x106'L\x13\xe0\x89\xd9\x17\x90\x96e\xe3'\x1c2\x105\xbdɲ\x1f\x837\x03x\x99\xf7C\xc0\x04O6\xe3{\x9db\xcdǿ\xa6,{\x8am3\x94\x17\u007f4\xbe\xaf\xdf\xfe G\xa3b*\xfdE\xd8\f\xc8;\xa0\xe9ڟ\x0f\xaa\xb51U\x91\x06\x04\x91%or\xc4'8\x19!\xf6\x9d\x9b\xc51\r7\xc6Y\x8f\x8d\xdd\xf0\xe73\xdd\xd4v\f\x88'\xd5v\xcc\a*A\x17㚹j\x010\xa2\xd2+\xce8\xf7\x8aj\x024\x9f\x19\x18\x03\x15R\xeb\xf42\xe2\xd3\xe9\xd16wiG\x18\xbcsu!\xaaˆ\x9b\xd7\x19\x9a\x8d|\xbf\xe0#\xe0\x1c\xbckQ\x92\aʵ'\xfaJ\x99+DO\xaa\x0f\xddU;\xa8\\\x04<\xbd\x95L\xe8UV\x9f\xd1\a\\\xcb5f\x98\xf5\x9d\xb4\x1d\xc64MEroԑ\x9c.\xe0\xe4D\x91Wo^\x1bR1Z\x87\x11\x19\x01\x12\xc1\x0ef#\xb1\x85\x14+\x96\x1a\xd5\xe9=\x95\x8c\xce2c\x04\xcfA\x02O@\x91/O\xdf_\xbc\xfb\xe9\xfa\xe2\xcd\xe5\xf3 \xe0\xc6t\x86ǂrC\x83\xa5\xf2Ҽ\xda}\xb3\x00\xe0+&\x057\b\n\xc3\xc6՜P\xb2\xf2\xb3M\xaa\xe4;cje+\xa7\xcd\x05A\xacV\xec\x1d!\x8c\x17\xa5\xf6\xde\xd1\a\x96ed\x16\x06\xb1\xe4ɒ\xf2\x85\xc1\xebkQ\x9ay~\xf9%bEBZ&\xee`\x06At\x87\xe9\xcb3\x17\u03a2Y&\x1e\x14\xca\x16P\t-\x1c\x8e\x83`6\xb6\x97\xa85\xd7\xf4\xf1%aS\x98\x92g_6\xfe\xf4,\b&b\xab\x90\xc2,\xd3\xc6#,\x163\xa6AҌ\xa1\x13\xb5\x84,;\t\x98e\x90\xb8\xb0#\xd8\xdem\xbe\x16\x12`\btL\xd8\xd1\xe6\xe8\x97\x15\x03\xb7_\x9e\x92k\xa1\xf7e\xa0\xed\x1e\x95\bC\x1cO;y\xfc\xe5\xf5ݻ\xbf\u07fc\xbd\xba\xbe\ve\xedM\xb1\xb0\x9b\xd5\xc71ɖX\xe8`\xf5a\xbb\xbfO,\xb4Y}\x10\xdc\x1dba\x8bՇ!\xb6C,l\xb3\xfa0\x16\xbc-\x16v\xb0\xfa \xb0\x9bba'\xab\x0f\x82\xda\x16\v\xbbX}\x10\xc8n\xb1\xd0\xc1\xeaÅжXh\xb3\xfa0\x88\xbb\xc5\xc2\x06\xab\x0f\x02\xdb-\x16FV\xdf\xf1Z\x18\xab\a\xbe\x8af\xf3\xdf9\xf3\xab\xc1\x8a\xaa=\x0f\xa3C-0\xe3\x80\xf16\x9f\xeb\xd2\n\x9e\x16\xf3m\x97 _\xbd\xa7\xed\xb4\n\xde\\l\x10dR\x1f\a\x9f\xb1\x8db\xad\xb2h\xc3XL\x8c\x95fǡ\xc8Y\xf7؎\xa7\xb9\x8b\"\xf1\xf8 \r\x9cL\xc9\x1b\x97a@ɫ\x9f\xae^_^\xdf]}}u\xf9.\f)$\xfe\xec\x10\x9f42\x105'\x1d\xe6a\x04^\xf6k\x0e\xc1\x02َB\u008a\x89Re\xeb*\xbd}\xf8ѵc\xf3五\xb25Q W,\x89\x99m\xe7Ԇ\xa8:v\x1cTx\xe2W\u007f@\xed\x89\x00\xbc\xdb&v\xcaO\fi\x1d\xd32v \x9f\xc0>\xb6〕\x1c\x01\xf1\xb8\nTc\x96{ը\b\xa0\xfbml\xd2;q\xb19P\xfdz\rsZf\xd6\xdb\xf6\xec\xd94D\x97\xb1c(\x8b\xfdZ\x8a\x9e\x01\x94\xe6h\xb1\xd9[{\x01\xcbG\f\x8e#\x84N\\blK\xedP\x81\xf6\xaa\x1d\xcc\xe5Nz\x9b2(o\xae\x1e\xf1R\x9eؐ\xf4\x9c-\xde\xd0\xe2[X\xbf\x83y\f\x88M\xb4cάK/\r5\r\xea\x81Z\x8f\x9dZ\fW\x1c\x8a\x17\x12\x92Q\xdc5Z8\xb9s\xd9Ϩ\xc3\x1a\xf4\xc4-\x89\f;X~\xc4iw~\xb4U\x99\x86\x9a\x17\r\xb1\xf2\x87辆[\"x\x02\x85V\xe7bet\ax8\u007f\x10\xf2\xdeXb\x0fL/'6\x1e\xa6\xce\xf1\x1a\xce\xf9o\xf0\u007f\x06\xcc\xee\xee\xed\xeb\xb7/\xc9E\x9a\x12\x81\xac\xb6T0/3\x9bv\xd7;ӷk\xd4u\x14\xce\xf0.\xff\x19)Y\xfa\xe7pf\xeb\xc7\x11hC\x146\x13\xf3H\xf4q\x8b\x91\xfc\xb5\x97R\x03peXx\xc5\x11\x88\x90\x18~\xeb\x93\x06\xbb{\xf8\x84e\xa7\xe8\x0eD\xfbL\x88\f\xe8f݊~\xa3\u007fh\xb8k\xf4K\a\xee\x1a\x01\xe1㮁'\xe08R\xe3\xa4\x16\x1b\xfd\xd2Y\xbb\x8738\v\x91\xbe$\xaa,\n!\xb5\xaaj4L\r#\b\x8bgԣ\x05\x04\xef\xf6\x9d\x91\xff\xac~Ļ#ꇓ\x93?}{\xf9\xf7\xffsr\xf2\xe3\u007f\xc6~\xa7\x86\xd9(\xafs\f\xc0\xaa\x80d\xcaE\n\x86e\x9f\xd9\u007f:\xcb\xeb\"\xc1\x04\x99\xeb\x01\xe8Q\x9a\xeaRM\x97B髛3\xff\xcfB\xa4W7\x03A\"\f\x15\xa1\x82\x92\xa3(\x01\xbbj݄\x8c\x16\xa5\xfb\x9a8\x83\x85\xa6+\x9fc\xe8\xfdksdn\xa8^\xf6O\xb1\xeb\x1a\x0f\x92i\r\x1cmU\x90\xb9\"b~f\xb8#\x9a\x02Cx\xb7 \xcfV/\x02#\x94-\x00\xc3\x05\xdbܣ\xe8Hۈ\xd8v\xecf\b\xc7\"\u07b5i؟\xf7\x12Tٔ\x03\x80^\xdc\\\xf9ZK\x1f\x11\xf1C%[\xb5m\x1fC\xbe\xf9\x84\xf3\xaf\x9fD\xcey\xe8\xc3D]\x9dSl\xef`\xf4\xbbɻ{d\f\x8b2Q\x9eօ\x99N\xed\x8fӤ(c\x99\xb9\x83\x90C.\xe4\xfa\xcc\xff\x13\x8a%\xe4 i6QZH\xba\x88\x16?~\xaa8\xc5\xfa_\xf6s\xb1\x9c\xbf\x81\x82홆%\xf14\xa0J I)\x8d\xb5\x93\xad\xbd\x8e\x02\xe9G\x93o\x15\xfdtW\x85\xea;\xdaD^'\xab\x0f\xb35k\xfe\x81n\x9c\x95\xc8\xca\x1c\xd4Ye\xa5\f\x00\x8c.M\xbe\"+*\xd5G\xb5\xb8R\xb6b\xaao\xbatנ|\xfd6\x925\x11\xe4\xb1v\x11\x8ckX\f0\xd1&\xc7@F\xa7\xf9\xe8\xcaG\f\xd8lQ\xea\xa2\xc4\xe4\xe1\x9c\xea**\xf5X\x888ϝ\x1f\x8d\x82>i\xd3a\xfa\"ƍmGA\xb5\x06\xc9_\x92\xff8\xfd\xc7o\u007f\x9e<\xff\xf3\xe9\xe9\x0f_M\xfe\xfd\xc7ߞ\xfec\x8a\xff\xf1/\xcf\xff\xfc\xfcg\xff\x8f\xdf>\u007f~z\xfa÷o\xbe\xb9\xbb\xb9\xfc\x91=\xff\xf9\a^\xe6\xf7\xf6_?\x9f\xfe\x00\x97?\xf6\x04\xf2\xfc\xf9\x9f\xbf\x8c\x9e\xf2\xe3\xa4\xf6\xd0L\x18\xd7\x13!'\x96\b\x0e\x16{\xd87\xa57\x1e\x8c!\xff\x84f\x19\xa4\x84\xe59\xa4\x8cj\xc8\xc2\xfd\xe4\xbe\x02h\xb3ܣ\xed\xf0i\x8bIF\xe9\rK\xca\xd3\f$\xd6+t>\xc0\x16|\r2g\x9c\x86\x16\f!Uz\x17\xba,!%4I\x84L]-8_ً\xcap\x8d\xbf\xe2x\xa8+5$\xcff\xbe^0\xe4Y&\x92{EJ\xaeYV\x97\x87\xf4\xb5!]o\xca`\xa8Q,\xa6\xfa\xcfIu&&؏\xec\xfc7\xf5\x9f\xf0\x87P\xe5w\x88\xe5ӯ\x9e\xef\xf6بA\tH\x1a\x98L)\xc2Ŗ\x1f\x98\x17,\x8c\xfab\x88\xaa\xae\xafZ\t\x9a8#\x03\v\x10\xb7\xbb\xeaPd\x9bX\x17\x8d\xde\aV!\xb1ch\x8eBD-\xa0\xe6\xd8S\xb68:\xd6\xe8\v\xdbf\x8cC\xb3~1Ú\xa8\xf1!\xcc\xe6\t\xb6\xfc\xc8Y\xa8\xf1A`&\xb1\xc7ȺQ\xdb\xd2\xce}H2\xbf\x14B\x93ӓ\xf3\x93\xe7[A\xad\x93x\xa8s\x96\x81\x95\xae\xb6\xc8RRmV4H\xc5\xf2\"[\xe3\xfe\x9c\xa4\xd8\xd1\xc9]\x87\x95e\\\x8c\x98 S3\xbb\xec\vB\x9d\x11%\x88\x96\xd4w\x19\x88\x9f\xab\x81f\x80kY:]\xe5\xf4\xe4\xe7\x933\x02:\x89\xcd\a&\xe4A\xf0\x13\x8dd4%w\x82\x94\xaa\x9ex4̵(\t\a[\a\x00\x1e\x8b\x8c%Lgk\x14\xf3\xd10E\xa9m\xf1El\x90\x88\x85\xb6.\x1f\x99v\xf7t\xe2\xc1\xce\xc9Wxڭ\xaa@\xa81\x86Vp\xbe\x04\x9a\xe9e\xfc\xfd>C\x97\\\xf0\xc9\u007f\x83\x14XƋ;\x88\xb1ޝ\x88\xd8Ys\x1c!\xe3$ƍ\xb0\xf9vd\x12\x83Q\x10\xbe\x81`\x95\x93lu$\xbd\xbb\xbb\xf9\x06t[\x84E\xa1\xc3\xcc\xc8\xe7\xe7\xa3K\x1b\xe4\\Ȏ.Ç\xc7P\xf9\xb7\x14*\n3d\xbb_\xabҶ\xfb\x845Rx\x9c\xcf\xd9\x0e-\xdai\xc9.\xa3\x91\\\xdd\xc4'b\xfd]\x94\x06[3:\xcb\xd6U\x15Y\x05\x9a<3S\x8fO{f\x1c\xf7\xf3\xaf@S\xac\xdb˕\x06\x1a\xa9\"\x1d\xe1\xa85\xe6r\x1c\xa5\xc6\xf6\xdd]Z\x90\x03v\xb4Y\x02\xcb\xd1\xfe\x14\xcfT<\x9b\xb4\x15^$\x14\x96\xfd\xba9~$&\xb9\xc5+\xec.\xb8\xdfg\x83r\x13\xa9o\u007fl\x97\xe8j;G\x16\xef\xf0\x83q\x9c&\x1e\x8a\x01\xb3\x1b\x9e%L\x06g\xab\x92\xae\b\x98\xc5\xd5 \x98\xee\xeeexZ\xda\xe68\xca\xfd\x92\xe8\x12^\xcd\xf1\x94h\xc2\xe9}|<\rK\xb5$q\x89\x88\xedׇab\xe0\r\x052X\xdf\xc2\xcb<\xd1\u05cd\xb7/\x1bkAh\x92\xc4\x15\x8a\xb2\xc3u/G\x86\xa5@\xaeB\x13\x1c\xeb1\x98\xc4\n\x11\xee\xbf\xf4cЅ\xb7\xe3\\w;\xcae\xb7\x8ez\x89\x92\xf02\x9f\r\xe0$U\x01\f\xa9k\x82q\x1b?\xc0\x99R\x15ۼ\xc6\xe9\xf9\x10\xee\x10}\x0fU\x18\xca\x17@^\x98\x99\xfe\xf1\x0f\u007f\xf8\xfd\x1f\xa6\x88\x86h\xa8>\xb0L9\xb9\xba\xb8\xbe\xf8\xe9\xf6\xfd+,\xe2\x16K\xe5Or\xb3\r\xcb6D˟vd\x1eA\x19\xec\x95\n\v\x9d\r\xd9ack8\xff\xb7u.\xab\xd88[sh\x81\xec\xe6#\xf1\x99!Bl\x82\x87\xe8C\xdb\xd9:)nEr\u007f\x04K\xfb\xe4\xeeՍ\x05U\x1b\xdbQ\xbb@\xb9w13\xbe\x12\xd9\xca\xf6\v\xbc{u\x83\b\x8a\xdbY\xf36\xc6\a\xd0շ6s\xf47\xe1mjN\x14T\x96\x17\xaec&%\x12hƔf\t~\xab\nSD\xda\xf7\xe2>&\x8b\xe7\x93\xf1+\x9c\xbc\xf5\xe9@\xe8b\x88>\xcd\x1b\xae\x89\x96\x8ba\b\x8bh\xb8&b\xaft\x8d\x1a\xc9\xd15\x12+\xea\x85\x1c\xa6Ǐ\x1aɧ\xad\x91|n22\xfa\xd5B\u00ad\x16\xc5\xc0\xac\t\v\xe4H9\x13\xbe\x13ݮ\xa4\x06\x92Fl\xa9\xed\x1d}qsUy\xc7E+\x11\x01\x93W\x82\xa1\xaa2Y\xfa\xd8\f\a\xa5\xce1=\xa2,\xac\xe7\xcb7\x94\f\x8fX\x15\x12\xb0\v\x9f\xe0gUE\x02D\ap\xfb#\xe8$\xfc\xb4\xa0O\xc6厸x\xa2߮\xa1i\x18\x89\xa4j\tة\x02\x1e\x99V\xbe\xdb5U\x82\xdb\x10\xae\xdb>&\xc2\x03\x98L\x91\x82*e\x03w\xba^\x84\xfdȍHO\"\xa2\xb7\x8d\t\x91\x85\xa4\t\x90\x02$\x13)\xc1\xaa\u007f\xa9x\b\x9f\xe7\f\x16\x8c+O\xbff\xa2\xfe`\x18]\t\xa2\"\xc2u\xe7\xd9w\xad.Rخ\xbcԉ\x88\xe0\xc3\xeeu\x87\xc5\xcd\x04\xa2\u0ad38Ms|J\x9ae\xeb\xfa\xa0\xfa\x9b\x9e\xfa\xf8\x9b\xb4\x9dI\x14\x8b\x84zݛ\x99D\xe1\xd1\xc0V\xe6\x919\nuV\xd2\x10\xf2oQ'S\xe6T%\xcb\x01m\xbeHx\xfa\xf2\x98\xdatp\x8c\xa9M\xbdǘ\xda4\xa66\x8d\xa9McjӘ\xda\xd4\vĘ\xdaT\xcdhLm\xda3\xc6Ԧ1\xb5\xe9\xf0\x18S\x9b\xc6Ԧz\x8c\xa9M\xbdƘ\xda\xd4c\x8c\xa9Mcj\xd3\xce1\x06\x12\xc7Ԧ_c qLm\n{}Lm\n\x18cjӘ\xda\xe4ǘ\xda\x148F\x8ddLm\xfa5j$\x9f\x9b\x8c\x1cT],\xf05\x9f\xc7s#\xc5l@\x99\xb1\x1b\x8cճĥ\x01\x89ytm\x1d;\x9d)y\xd5J\xcfpM\xf8m\x95\x96 \x88.ѧNO\x1aZ\xaf'\xb8&\x93/\n\xa6\xce\va\xff_\x9dS\xd0H&\xb0\xfe\xb5\x10\xe1\x10+|c\xb2\b\x0ee\x10D\xf1\xba\xfd\xd9\x03\x98\t\x10\f\xf3\x98\x99\x03C\xb4\x9b\x01\x19\x03{\xb2\x05<\xd8(\xe6ڝ)\xb0\x11\xf1\x8fN\x05qY\x02\xdb\xd1\xfe!\t\x17\x98\n\xb7\x15鏄Xe\a\xec\x8a\xf2ǩ\xe4\xea\xf8\x11\xfe'\x88\xee\x1f?\xb2\xbf'\xaaO֢\x8c\x82\xb9#\xa2\xef\"\xf3\x91\xb4\xd9\x19\xcd\xf7Q\xf98\x98ݑ\xfcVD>\x96\x98\x06E\xf1\a\x04\xa7\x06*\xd7\xf1\x9e\xe4hM\xc9%\x1b\xdf-%\xa8\xa5Ȃym\x8bϾa\x9c\xe5en\u06042쑭\xaal\xe6p\x1a\xf1yNV\xeb\xb0a8\x03\x98\xa5\x80M,)\xcbbJ\xd5ai\xbd%E\xff\x84*\x93\x04 5r\xf2u\x1d\x02\x0f\x86\xf9\xfbi\xb5r\xdbU\x83)\xf2\"\x94\xf2lCE\xb4\xef~\xff\xbb\xa8ݏ\xb1\f#\x136\x0e'k \xe4`L\x0eO\xd4\x18\xa2n\xc4:R\x9e&9cOb\x06\xf9{\xa4hؓ\x94AX\x9c\x98=RB\xc6 \xce90\x11cO\x12\x86\xc3Q\xa4\x02\xb2\x9d\x80\xb1\x99H\x11\x87\xf2\xf8\xe4\x8b\x01\xb2\xed\xa9\x92.v'\\Ē$\x19\x9cl1<\xd1\xe2\x88\xdd\x0e\xeb́\xc1\xdd\xf1\a\xb9\xe8\x8e\xe09\x1c\x98T\xf1Th9F\n\xc1G\xec>\x1b\xbd\xabC\x92'\x06&N\fI\x9a\x88M\x98ؓ,1\xc4\xd3<0Qb\x10\xf9Ć#\xa2C\x11\xc3\xc3\x10\x83C\x10{\x12\"\x86\xf4\x84\xed\f=\xc4\xf6/\xf4\xa3\x1dv\xd8\b\x1fD\xaa\x85͐\xc3QC\aG\x0f\x1b\xc4'1\xecO`h$\"\xc4\xe2p;yaH\x12\xc2\x00\x8a\x8ee\xfeQA\x95h\xa6\xcd8ӌf\xaf!\xa3\xeb[H\x04O\x835\xa3\x8d\x86H\xd5yU\x16\x9c\xb5\xcc\xc33!Z\xb71\x97\xd4u΄\xd4_\xa8\xf5ѐp֊\xea#\xa1\x18\xa70\xab\xd7\xedۓ\x1f7nA>\x9a\xcb\xc0^)=\x06\x11\xfcU<\x101\xd7\xc0\xc9)\xe3\x9e\x0e\xc2\xfd\xa8\xb5\xb3\xa0\xf6\x17U\xc7\xda\xfc\xf5\xc5W\xe1\x9c\xcbN\xe6\xf3u\xec\xa0kK\xa9\xa7\xf3\xeb\xb9\x0f\x1c߱\xe7\x00\xcf\xcbp\x1f}˹g\x1d\x84m\xfe\x1e\xbcyu\x1b\xbe\x178o\xcfM\xd0K\xed\xca6D\xc0\xfcL\x89*:\xed\xec`\xca\x19\x89\xe8<\xb6/ݬN\x1d\v\x06\xbb#լN\x1b\v\x9f\xe8\xae4\xb3\xa8\x94\xb1\x8f\xee\xe1\xdcH\x13\x8b7?w\xa4\x889\xf5,R\x89\x8fN\x0f\x1b\xed\xb0\xc0\xb1'\rl\xb4\xc3>!;\xec\xf3\xb00\x1a\xb5N\xbe\x914\x81\x9b\xa3\xa9\x99\x9e]\x91\xb4\x94ԉ\f\xaf\xe0E\xd9\x1b\x86\xc9p\x80\xd4r\xaa\xaap\rV\\\x99\x97YD\xf1\xaa\xb2\x10\xbc]\xfd\xc9\xe6T4\x8b\xb8\x04\x03u\xd9.\x1d\xabv\x8aR\xcc\t-\xa4\xb0j\x1f\x91%\xe7F꺳d\x90bl%\x15'!\x9b5{\x14[\x98\xed2*\x16V\xc1a\x11\xf2\xe5a\t\xdck\x99n\xc2fvs!\x136\xcb\xd6dI\xb3\x98\xf0\xcb\x03\xd3KB\xc9=\xcb27\xcd)\xb9\x05M\xf4\x92\xa9Hgj&\xf8\x027\x83\xda\t\xc3c\x01\x89Q;\x92\f(/\x8b\xb8\xf5\x1beu-J\xe9\xd7\xef\xda\xc6\xf9Y\xc6$mp\x96\x9d\xf9\xad>Q\xfb\x0fl\x04bm\x82b\xa9\xc0\xd7iz`\nΆ`ַ\x19\xb5\xe7\xc0\xae\xbb\x90b\xc5RH\xc9l\x1dG\xff\"E\xaduJ\xde#<\xcf\xf7\xb9\xe0\x13\x0e\vjl\xa3\xf0\x93j\x85\xb8=\xf3v\x9e\xb6\x1e\x05OYBu\x84\x8d\xa5\xb0\xb0^]N\x8f\xac\x18E,4(7\x18\xe8)\x17D\xa0R\\r\xa6\xd7\x18\x1b]\x96\x9a\xa4\xe2\x81?\x9fb\xeb\xd9\x18&E\xc9\f4u\xf7Zm+A\x14X\x8a\x00\xa7\xb3,F9\xc1LܻN\x02%s\xa0\xba\x8c\xe8\uede0\x1a:\xfd\x01\x96\x1e\x8e{\x1c\x98r\x11\xd09)\xb9\x82\xe0\xfb3\r\xfb\xf0\x8f\xff\xfa\xe1\xecC\x96\x83(\xf5'\xe5 |X\xb2d\xd9\xf47\xb0\x1c\x14\x11\xe5\x90kkZ\x90\x17nZ\xdd\x14\xf1\xc4\xed#\u007fq^\xc5(\xad14\xc4\xde\x117ڬ\xe6W%N\a\xad\x9b\x1a\x1e\xf6\xfa\xfa\xf6\xa7\xef.\xfer\xf9ݔ\\\xd2d\xd9,C\xca\t5r#\b&ʕ%]\x01\xa1\xa4\xe4쟥\xed\xe0\x9e\xc4E\xa7&m].\xf0]O\x05a\xd6ِ\x8a\x02\xa1\x89έ\x10\xa0\xb1`&9-&\xf7\xb0\x0e\xd2y\xe3\xb1\x14\x85\xa3\xedI\xdb\xc5\xe7\xb4\xffM0\t4e\x9fP1\x05ǥ\xeayuWU\xc8\xc5*\xd0i\x84֞\x87\x0e<-\x04\xe3Zu\x95Z\b\x02\xbbm2~2)\x8bc\xa9\x85\x8e1\x96Z\xd89\xc6R\vc\xa9\x85\xb1\xd4\xc2Xj\xa1{\x8c\xa5\x16\xc6R\v\x9fU\xf2\xf4Xj\xa11\xc6R\v\x11c,\xb5\xb0k\x8c\xa5\x16z\x8d\xb1\xd4\xc2\xf6\x18K-t\x8e\xb1\xd4B\xc7\x18K-\xf4\x1dc\xa9\x85j\xfcr\xae\xf8\x8c\xa5\x16>\xd5+>c\xa9\x85>\xe3\xf3\xb8\b5\x96Z\x18K-x\xbc\x8c\xa5\x16\x82\xc6Xjac\x8c\xa5\x16>W\xa2\x1aK-\x8c\xa5\x16\xc6R\v\xdd\xdf\xfd\xb5\xdbac\xa9\x85O\xd5\x0e\xfb<,\x8c\xb1\xd4\xc2Xja,\xb50\x96Z\x18K-\x8c\xa5\x16\xc6R\vc\xa9\x85\xb1\xd4¯ȫ\x18\xa55JP\xa2\x94I\x98\x1d\xdc&\xb2W\"/J\r\xe4\x9d\aU)\xcbA\vGY\xc2T\xf3F\xff\x87\xedD\x98\b>g\v\xa7\xe8\x9d\xe7\x94\xd3\x05L*\xfcL\xea\xfbw\xe7\x1f\"7>c9\v+\xb2`F]\xb1\xe0f\x80\x87#Ҡ\x1ejN\x0f4\xa6\v\xaa5H\xfe\x92\xfc\xc7\xe9?~\xfb\xf3\xe4\xf9\x9fOO\u007f\xf8j\xf2\xef?\xfe\xf6\xf4\x1fS\xfc\x8f\u007fy\xfe\xe7\xe7?\xfb\u007f\xfc\xf6\xf9\xf3\xd3\xd3\x1f\xbe}\xf3\xcd\xdd\xcd\xe5\x8f\xec\xf9\xcf?\xf02\xbf\xb7\xff\xfa\xf9\xf4\a\xb8\xfc\xb1'\x90\xe7\xcf\xff\xfce\xf0T\x8fl\x9c\xb6\xcf\xe3wH9uJ\x11\xf2\xed\x9c>\x1a\x06\x1bN\n\xb9(\xb9\xb6\xb7l\xec1\xafN\x84M\xc3\n=\x94\xe4S9\x98d\x88\xa1\xed\xf2\xd1\xc6\xf3\x190\xc6\xf3i\xcf\xe7;G;\xed\x13\x1a<\xc7ܩL{Nh0L/\xb8\xd1Э\xe6\xc9\x14\x119\xd3Ɯ\x8e\xb9f\xdc(\xa4\x82WR\x9a.j˫µ\xbc\xb9\xbdM\xc1T\xf3\x82F\xe3R\xb8\xf0\xb6o\x8cZJy\x1d\xa7@\x9e3Ia\xce8\xa4V=\xfd\xf5\xf1\xbb\xa8\xd7\x14$\xa5dz\xfdJp\r\x8fA\x8e\xfd\xf6y\xb9m\x03\"v3\xc2\x0f\x8d\x9f\x10\x11\x85\xbdv\xb4Q!\fo\xfe\x85\xa9\xac@d\xc9џe\xeb\\\x80\xb6\xce\x1d4\xc3\xf1f\xcf\xc6\xe4\x83\xc0{\u05cb\xf5h\xfd\xb3d+\x9a\x01\xd7\r\xe87h\x1c7?\xf0\x14\x1a\xb2\xa6꾦J\x98\x18S\xa9\xc2۹G+\xfe\x04\x8f\xfa\x83hǨz\xdcH\xb6b\x19,\xe0R%4\xc3\xd32\xcc\\\xbe\xd8\x015\xf8\xc0\x1bTH\x91)\xf2\xb0\x04É\b\xf5.D,\xb2\xb0\xa0\x11Iٹ٫\xc2ONY_\xa7Q\xf4\n*\rUx\x1fe0`\xacE4\x13\"s7&\xb3u=\u007f\x16\x17\x82\xe2\xe2'\x0e\x0f?\x99\xd9*2\xcf\xe8\xa2rM*бi\xa2\xf5Q\xadܱG\xdb0\xa6P\xae\x13\x9a=е\xaa\x1d\xdfqW\xcb-ė\xe4\xc5s\xe4\x0fT\x91j\x8e)\xf9\xdds̰zuq\xf3\xd3\xed\xdfo\u007f\xbax\xfd\xe6\xea:\x8e\x8f\x9b=\x83\xc0\x98\u007fB\v:c\x19\x8bQ<\xb72Ǜ\xc0Pp\xa6\xe9y*E\xf8\x95%ķ\x8f\x85\xd4\xf2m\x98w\xa9Y\x11\x0e\xc9nޚp\xb8\xefRR\xae+\xa7w\x83\x1ce\xc95\xcb?\xe8\xa5n\x9a\x0e\xbf\xd0}\x91\xa6\x90\x0eC\xc9\xf1\xee¼\xf2\xd3X\xd7\x05颠\x12r\xf3\xf6\xf6\xea\xffn\xd0\xe6\xba\x18\x92\xa0\xff\x11\xee\xa2\x12b\x0e\xd2\xe0=~g\xebW\x8c\xbb\xbcw|~7\x8e+=`XN⻒\xb7\xcb\xd9\xd6p#\xf4\x93\x14\xa6䦊\x14\xb7\xa05\x98z8\xaf\x93@\fH\xae\x19ͲuS\x13\xd6\x02k2\x84\a5\xf9\x8e\xdc\xf59\xcdT0#\x8f\x97\xc6F\x91yc\xcc\xf7A\xbbXA!)p\xa1\x9d\xc7/\xea4\x889B#֧и,ВxQJf-\x8c\x99\xf28\xbf\xa9f\x8e\x11\xa6\xf0\x94\x0f\x05\x9bf\x9c\x13ƕ\x97!*\xe8/\x81\xa6XS\xa6\xa0zi\xf3Ts\xaa\xee!\xb5?D\xea\xd8UH\xd6̸Z\xfaݺ\x80\xe8x*\xea\xd66\xfb\x17\xe3\xbc\xe1\xde\xd8\x01\xe5\xbdh\xfa\x96g\xebwB诫2&\x83\b\xf9{g-\xb5\xe3@\xc1HYb\xd9n3\xbf\tn\"\x96miVZq\xd4\x17c%|`\x06!K~\xa1\xbe\x91\xa2\fV\x05\xb6\x94\xf5o\xae^#\xbf,]\x86\f\xd7r\x8d\xa5\xa9b\x98D\xfb\xccU\xf6\xd8\xdf\\NST\xb6M\xc5\x1e|\xb8\x9e\xbc\xa1kB3%\x9c\xe1\x18\x11\f\xee\xf2\x90\x10窉\xb9\x19=\x13z\xb9\xe9\xd3A\xf6\xb0\xfd\x9d\xf0\x02Fu\x82M\xe5\xc94K\x18\xe2BB\xb0\xf4\x1e\x14)$$\x90\x02O\x82\xa9\xf7\xe3\xa4A \xe5_\vn\xd8\xcb ڿ\xf2\xf9?\xd6e<̪\xc7L%g\xd3S\xccWB\xe6R*\x9069L\x96\x10\xb7\xf1ߖ3\xc8@[G\t\x16\xb9\xa5\xdaz\xfeXN\x17ᧉ\xeaJ\x14jA\x80\xabR\x82s\x9ak\x92\x8a\b3\xc0Ց2K\xff\xdb\xd5k\xf2\x1595k\u007f\x8e\xe4?\xa7,\x8b\xa9\xfa\x82\xb7?6\xb8\t\x9b\xfb)\x1a\x94\x86\xeb\x04\x1c\x8d}iY\xf5\x19Ⴈ2Yz\x9c\xc6x\x87\xbc\xf3\xcaݐ\xc2+l#k\xfa\x04X\xd3@\xc1\xfa7\x05r\xb0\\\xfd\xdb\a\x90\xabC\xdc`\x867\xb5w\r\x19\n\xc9AӔj\x1a\x13|+y\xa3:\xe2\xc6Q\x88\xa1\xdd\xfdG\x01I;\x18\xe6\xaf\xec(|\x1c)\xad\xe0;\xc6\xcbG{;`\xb8C\xf9\xf6\x12\xc1\x11\x17J\x8a\x91(3 \xb4(2f\xcb\xf7m\xb4\x88\xb9j\x91n\xdc\xdeo\x9b\x9a(\x1eh\x96\t\xa3fD\x84\xc7%\xe5\xa9ȷ\x16o\fQ\xa0\x11Vqc\xc1\x1d\x87s\xd7a\v\x97\xdd\xf5\xe1\xfc\xb5\x1d\xb6!\xae\xfb\fV\x10Q\xa5|\xb3\x89\x92\x81b\fRO5\b6\xca\xfb\x99\xd1\x19dV5\xb4'Gm\x9f\x9ch\xafh\xa4SU\x8alxɋw\"\x03\x9b\x1b\xef\x91d\xc0\xfebp\x84/\x0f\xc5\x11z\x9fZ8\x8a\xf6\xa2\u007f\x8a8*#4<\xb2\x89#\xa3&\xb6qd\xc0\xfeBp\x14\x1d\x82P\x90$\"/n\xa4\x98\xb3\xf0ú%\xfa\x1d\xb8:9'\\\xf4\x97\n\xba\xb2\xc8Q\x8fD\xe0\xe1\x1a\xb9\x9b\f\x95\x8dKOT[\x99\xe7nq\x05\x03\xfd\xff\x1a*\x04r\xed\xb3\r\xbd\xc2}5|\xb6\xcd|\xa1B\xa4\x1e\xd0\a\x95n\"\xa1\x19v$\x8a\xa3\v\xb2I\x1b\x9b\x00\a\xdc\xe7\"\xb6\xb1\x9d\x83\xe3s\xfa\xb0%\v\xfe\x12\xe1\x19 \xbe\xb9\x9fH\xa1Q;\xde^\xc0\xbb\xb3\xf7e\f\xec(\xc0\xfeZ\x9c\xd1S|\xf2U\xeacW\xe6\x8bq\xd3\x15\xaeT\xf6\x9b\xaa\xa7\x92A8\xf04\xb6\x12TA\xf5\xf2\x8cH\xc8\xf0\xe2\x9egh\xf7֡u\x12\xb7O\x8d\x05{\xce\xe07\x0e\xf5l&x\xdc%v\\5\x86\x05\xbcF{K\xccm_\xe2`\xff\xc1\x0e\xf7F\xed\xae\bw\xa6\xecqoXwE0ȏ\xe3\xdeX䊾\x92滚\xd1\xec\xb6\b\xef\xf0C6i\xf9\x9b7\xb7\x17m\x90q\x9c\x1d\xf3z\xa5U\x8f\rLBӜ)\xc5\x04'\x0f0[\nq\x1f\x05\xf7ԧ\xce/\x98^\x96\xb3i\"\xf2F\x16\xfdD\xb1\x85:w'{b\xb0\x13\xd7\xe4\x84\xf1\xcc\xdfz\xb0\x1eB\xae\x95\x8f\x18\x98\xc5\xc4iY\x15V\x91\x00]\xa7B\x97ຍ\xf6\xeb\xd8\"UxcძTۤx\x1dYP\xfc\x009F\xe3\xc5U\x97iT{\xb2\x84Y\xefK\x9c\xb85{iC?\x1f\xbe\x8d\x805\xd5\x12P\xc3\xdb\b\xfc\xb5\x86ER\xb0\xc5!\"\xed>6o5\xf4\xae\x15\x12\x1bю\xb4%O\xb0v\x9b\x9b\xe2I\xd3\xe9\x10Uǃ\xf8\xa3\x82ަ\xacX\xd2\t:\bP\xde\x18\x81\x16\x05\xd1\x1b;K\xc1\x85\xb4\xc7ۨ\xf4\x82G\xf4\xfc\xb6\x03\xfdW6\xdf\fi\xd6)\x1a\x8d\xedz\x15\x9f\xeei\x86K\x87\xc3\xf46\xac\rd\xd4\x16\xeb؉/S\xff\xc0\xf4\x12\xdb7-\xa1\xf5\x81x\xccJP\x98\xb0\xc4\tH)\xa4\xbb7\xe2\x13\rb\xeb*[\xfd\a/\xb7\x18\xa6@ͿNԐ\fZ\xd2j\x1fk>\xa0\fǁ\xf9\x1c\x124\xd9\x1b;\x17\x05܆hN\xeb~c\xeej\xb8aB曑\xc7+g\x8f\x06\x03M60\x10\v\xbe/V7\xc8\xe7SB\xae\xe2\fQ\u007f\xb1\xfb\xccp\x9a&tw\xb3(\x96\x14x\xab35n\xa2\v\xe7\xc5I\x06\xc0\xac^3\xa3x\xc9\x10\x93oA\x9a9\x17G\x11Ø{မ#\xe8\x98P\xacOl;\u007fc+\x1f#\xce9\xb6\x99\xc3\xe1\xfdc\xd11\x84=\xb9\x1c\x84\x85\x87q\x89͙:j>\aّ\xd3\x11\x9f\xddD\x9e:É<]\xb4\x99\x1c!\xe2L>J\x94'\xeeⷭ\xe8<\xb0\xcd\xefm\x03JãiT\x8f\xa0\xb5;qj\xab\xdaWU\xb1\xb3\xb5\xaf\xc6\xcf\xfe;4g\xbe\xdd~\x9e\v[l\xa0Y\xea\xde\xf55\rSSJ\xaeY\xe6\x83Wy\x91\x19\xe3\xb15\xe3\xe0lH\x84\xd5\xe87|V!\xa3no\xec\n\xfd\x87\x9d\x97\xffB1T\xb54\xf6\xf5\xbco\xaaO\xd9\xe8G\xa0\x06\xec\xda\xcfc\xc96-|\xbc\x8d\xa4l>\a\u007f\xc39P\xec\x15T\xd2\xdc\x18\x0e\x8a\xb8\xd4\xdf\x19,\x98\xbdfZ\xa9V\x81\x11\x8a\xaaHؙU\xf7\x98&9[,\xad\x97\x86P,E\x19^nR\v\x92\t\x9a\x12\xe4\xe2B\x92\a*sc\xb1\xd0d\x89\xf5\x1b)'i\x19|\xf0\xb1\x93\xdcz\xa24\xd5@D\x01\xb6\xa4\x84\xdd\x1b\x83o[]+\x8cL\xc7\xe6\xd3c\xf3\xe9\xdecl>=6\x9f\x1e\x9bO\x87\x8e\xb1\xf9\xf4\xd8|\xba\xf7\x18\x9bO\x8fͧ\xc7\xe6\xd3v\x8cͧ#\xc6\xd8|z\xd7\x18\x9bO\xf7\x1ac\xf3\xe9\xed16\x9f\xee\x1cc\xf3\xe9\x8e16\x9f\xee;\xc6\xe6\xd3\xd5\xf8\xe54=\x1b\x9bO\u007f\xaaM\xcf\xc6\xe6\xd3}\xc6\xe7\xd1\x1anl>=6\x9f\xf6x\x19\x9bO\a\x8d\xb1\xf9\xf4\xc6\x18\x9bO\u007f\xaeD56\x9f\x1e\x9bO\x8fͧ\xbb\xbf\xfbk\xb7\xc3\xc6\xe6ӟ\xaa\x1d\xf6yX\x18c\xf3\xe9\xb1\xf9\xf4\xd8|zl>=6\x9f\x1e\x9bO\x8fͧ\xc7\xe6\xd3c\xf3\xe9_\x91W1\xf2\xa6HʂZ\xb6\xf5\xe8\x16\x10S\xfb\xc4\xd7\xee4\x8c\xac\x9c\xcfA\xa2\xf0\xc5\xd9y\xe5(\xee\x12\x98\xef\fU\x89n\x97\x11\x8b\x8d\x02%\xd0\xd4ּ\b\xf3\vvN\xcb\x17!\xc5\xf6e\xf6^j`x\x80\\\xbe\xfd\xbav\xbaƴ:\x88\xbb\x1d\x88\xeby˓\xf8\xbbB5!tTg\ríM\xc0O2\xa1\xdc=YDv\xb2\xa4\x9cC\xe6\x94n\x16\x86\xd9%Ud\x06\xc0\x89(\x80[\xb5\x85\x12\xc5\xf8\"\x03B\xb5\xa6\xc9rjV\x10\xe6=sD\xe0\xba\xd6\xd53UZ\x02\xcd-1H\xc8C\xfb\f\x9a)\x12\x9aH\xa1\x14\xc9\xcbL\xb3\xa2\x9a$Q\x80\xa52\x02\x93\x96\xae\xe6\xf5\x06c\x92x}\x01\xf5\xacZE\xf0\x1cm\x19\xb4ƙ\xd7T\xea3l\a\x9b\x17zm\xefR\x85\t>\xec\xda)\x95&Iƀk\xb7j[\x9f\x11\xe7yFBs\xe3\xf1\xfa\xae\xdd\x05\xe5P\xcbS\xf4\x8a\x14Zٛ>q\x13uSL\x99r\xde7uF\xa8\xf6\x822\x98\xe8=-!\xd9{\x05\xce\xce\xda\xfd\x149ͺ\xa4\xbf\xaa\xaf\x9a\xd5\xccp\x9e\xd10\xc5\xd03\xa5\xb3V-\x87\xda>\xc4$wd\xabA`\xb1\xec\x90\xc5\x02\x1e\x1c\x0e+\xc3? \x01\xb6B\u007f\x90\xe1\x8cA\x107\xb9\xe8\x933ц\xee\xfa\x06\x94\xa2\v\xb8\tL\xb1\xd9\xe5 \xc6,\x9b\x9a\xb8\x02\r.\xacF\xa6EC\x87\xab/\xa0\xb4-\xd0 \xb0\xb9]ces>H\xa65 \x11c\xe7*\xcc<\f\xcc\x03ߚ\\\xf3z\xcc\x1b\xffA\xfb\xa1P\xaa5\xfa\x14O\xed\xa5\x8e\x19\x90\x99d0's\xc6i\xe6\xeea\x84]8\xc2~\x16T\x19ҤJ\x81D\x9f\x8bs;y܄\x11\xec\xf7\x0e\x91Z\x96<\xa1\x8d.\x97X\xfd\x8e\xcd\xc9\x02\xefz\x04\x1a\x13K\xcaɿ~\xf5\xef\u007f$\xb3\xb5т\xd18\xd6BӬ\xda\xc0\f\xf8\"\xb0\xb6\xbf\x13O\xed:d\x15%d,g\xa1n!c\f\xfc\xee~\xd6\x0e4\x9e\xa7\xb0:o\xd0\xe7$\x13\x8b0\x9c\xbe\xf2\xf7+\xab;\x93!\x8a|\x94k\xbf\x83\r\x88\x8c%\xebhF\xe0\x9b琥x\xb0\xae\xbc\x81'\xb6\xbe\xe2X\x88\xa2\xcclJ\xc6\u05fe\xb2d\x10\xc8R\xc1v5\xacN>\x18J\r~j\x9b\x1d\xc2\xed\x95)\xb7\x940\xa5\xc5\x15\x9es\xa1\xf1\xaag\x0e\xfa\x89\xbf\xa6Y6\xa3\xc9\xfd\x9d\xf8N,\xd4[~)e`\x9b}\xa4~\x8f\x8f\x8c\x1a-fY\xf2{ly[\xd7\x1a\x16a\xd2V\x94\xba(\xb5\xbf\xe4\xddt\xef\xfa\xcd\f\xae\aY)h\xde3\\\xcf\x0e\x1e\u0379E\xf7l\x18;p\xc5w,w\xc9Ģ\x9a\xb7\xf2\xcc \xf4F\xd0\xef\xbe\xfa\xd7\u007f\xb3,\x8b\bI\xfe\xed+\xbc2\xaaά\x10C\xdd\xc0(\xb29Ͳ\xd0`V\x93\xc1\x18\xa2\x9fv0\x89'\xe7\x11:\x9e\x1d<\x89\xc9}w\xf7w\xb4\xb7\x99V\x90\xcd\xcfl\xed\x11\xefA\f\x02z\x82J܉\x93\xb2X\xe4\xe6#\x18\xb4+\x91\x959\xbc\x86\x15K\xc2\"\xfc-T\xb7\xa0\xf8HPƔ&\"\xac\n\xc4,\x13\xc9=I\x1d\xa0\xc6\u074c\xcd>\xd6!\x98\x89\xb8\x85\xb2su\xf5\xfd\x13\x12ڌ(\xa7EQ\xd5r\x90\xf4\xa1\xb5X\xe4%\xc1\x17Phl\xa0:>\xab\xc3N7Ta\xf7\xef6\xb0Z\x03\xf2\x04S\x84J?;\xdc\xcd뭆T\xbe\x83^T\xae\x81\xdb\x13\xab\xa7\x99\x9dC\xce\x1c\x1e^\x1f\x90\xf4\x10w\xa7\xa7\x85c^\xe5\n\xe4T;\x9b&2\u007f\x06\xa9\xb6\x00\xa9\x982\n\xcc{<\x13\xaf2\xca\xf2\xf8\x1b\xfe1\r\t\x06\xb4\x80\x8d\xc9K\x984\xe84\xf0\xc5`D\x0f\xaa{\x14v\xb7Ų4l\xe9\x1b\xcf\xf5oD\xea\x00!\xab\xb6m\x98\x8d)\x1bL\x0e\xbb\n=\fR8\x86\xb2\xfd\xf75\x8e\x9a\\߮3\xfc8\xe3\x01\xb20\x1d\xb3\xff\x18\xec\x1b'\u007f\x04\xee\x8d|\xdb-chݹ\xa6\xc3\xc6\x11T\xc3\xf4r>\x92\xa9͍\x8d\x00o(\xc8M\x8f\x9c\xbc<\xf9\xa0<ܢ[\x8a\x82.\xd0\x1a\x19\x88\xf5Mp\xc3\n\xcd\x1a3\x19!V=c\x10.\xa4Um\xf3(\xa0\xf6B}-\x87\xbd\xf9\x84\x95\xc7\" >\xd05\xa1R\x94<\xb5\xb1\x87:(\xf5f\x03\x1dׂ\xc7L\xd9E\xbf]\xa5\xa9\xaa\xa6-\xa6\t0N^L_|\xf5\xb9\t~\\Ɇ\xe0\x8f,\xfc\xdc\xe0[\x1f\x14\v\xbee\xfb@L\xbcq.ֺ\xc3zT\xd9I\x1b\x03B \x0f\x92iG\xcd\x0fL\x019\r\xf5\x9a\xfb!d\xb3\x96\xe5\xf3\xb6K/\xaaw\xfb\xb0\xa2\xa7\xaa\x9c=\x81d\xb0\f=\x02=Ȅ\xba|\xf1*\x1ef\x87Xi\"\xfdYL\xa7\x8fS;\x9b\x13[\xf5\xea\xf9\a=$n\xcb.\x1f\x8b\x88\xceq\xadm\xbb|,(z\xfd\x8bz\xffb\xceI-\xc2w\xef_\x04\xdc\xddj\xc1_`IWQ\xf2O\xb1\x9ceTf\x98Zvk1If\xa5&\xc0WL\n\x1eu\xfb\x82\x90\x15\x95\f\xab\x8dK\xc0Z\x90\t(\xf2\xe5\xe9\xfb\x8bw\x98\xa1\x1dS\xb8˖\xe9t\xfbS*[^|(F\x1b\x8b\xdc<\x045IG\xc0\xb5\x87\xc0\xe3\xd3P&j\x00\x1e\xbf4\"U\x89\x90\xbc\xd4%Ͱ`[\x92\x95\x8a\xad>\xa4,\x8a\xb5\x1c+]\xfb\x17d8\xba\x92\x81\xafY\x10\xbf\xd9(\x8fX3\xf2\xad\n\x84\xc1\t\x1b\xa8\f\xd6\x15n;\xd3j\x02\xe9\xd87\xa8j&\t;\x87\xba\xab\x9ej\xaf\x10\xba\x9eo\xa1\xa9K\x1b\xd9\x069]|\x04\xd7z(M\aQe0=\x86Q\xa2\xcb\xfb\xec7\xf5\xb6Zl\xdft=\u05ec\xd71\xa7\x8f\x98PI\xf1\xb8\xf6\\\xa1\x98\xe3,\xc8{\xc8@\n/\x96\x1e(\xd3\xd5}Sƙ\x0e\xee,\x81\x86\x93\xad\xa7\u070f\x00\x82\xb6\xbe\xf7\xbe\xf4|\xf0\xf0\xb6\x1d\"\xb3\xbddup\x16\xfb\xbe\xbf\xe7eƓ\xacL\xe1UV*\r\xf2\x1d(Q\xca\xce\xe8\xc7Ft\xb9\xf3\xadƥ\xd2\a\x17pJ\xec#\x13\x95\x88\xa2\x93=\xc8\xfa\xe5J\x9fq\x93J}\xc1\t\xbc\x9f\\ݤ\xb1\x95\xbd\x94\x16\x12vT\xd6\xe6e\x96m\\j\xec\xec\x9b`\x9e3\xdaɎ\xbb]\xfb\xec\a?EcH\xaa\x82\xf6FY\xe3\x05\x9b\x80\xaf2\x96\xa0Þ\xfb?\xd8\xff2\xb3v\x1f\xe9X\xa1\xddK\x9b\x84\x8ayY\x18\x9d=\xc3\xe4\n^\u007f\xc1VP\xb0\x1f\xde^\xfeN\xa7\xe0ރ\xd4\vi]t\xe8'\x12Hd\xf5\xf3\x1b\b\xf3\x94\xd3\a_\xdbd\xd3\xc4XM\x83\xee\xb9\x19M\xee\xcb\xe2\xd3B\x1fv\xa0\xbe\x85\fu\x83\x03\xa8\xfb\xae\xf9\xacE[\x0e\x9a\xae^L\xdb\u007f1\xb65\xcb4f!w\xaaf\x0f6\x13\xd2`\xcd^8Kي\xa5%\xcdZ\x14\xd8\xc0Y\x8dZ\xbc\x90ʲ\xae\x04),\x89\xeb\xdeoḺ0\x18|V\xf7{\x81\xd1\xf1c\xd4o\x97\n\xdb͂\xdb\xeeōW,\x16]\x1c\u05f5\x03W\x1e\x8f\x8e\xb5\x1b\xfbag\x9a\xed\x9d+H\xe8\x9fÕ_\\\xbfޥ\xde\xecuٷ\xa6z\xb1g:\xee\xccT\x1b\xbe\xaf\v\x83S\xc4ܝ/uF(\xb9\x87\xf5\x99M~\xe5\xae\f\xbd\x03b\xbb\x06;\xb5\xe1\x1ev\xab*\xe6e\vo\x17b\xfa8\xf0\xefa\xaf鉶\x8e{XWawċ\xf9\xc1\a@kT\xb86\xee\xfbe\xff\xde(g/}\xc3c\xad\xf7\xf4+4K0\xc4gIŬ\xe1D\xb9V͂\xab%+\x0e%\xc7PL\xd9\x16s\x8f\xfd\xaay\xaf\x05o\xe9\uf29f\x91k\xa1\xcd\xff\\>2u\xe0B\x8e\xd9\xcb\xd7\x02Ե\xd0\xf8\xf4`\xe4ة\xf5F\x8d}\x1cI\x9a[\x1e\x89\x97\x94\xf0\x1b\xd52\xaf\x0e\xdf\u007f\xafP\xcc\x14\xb9\xe2\x86Q9\x1cT\x97\x15\x95\x03\u07fcc\x88\\m\xbf&j\xbf݂o\xd1j\xbe\xd1\xc4\\\xf3S\xfbQޚ\x86\x9d\x82\xf5hۿ`\x82v\x91\xd1\x04R\xd7g\xc2l\xbc\x96TÂ\xedo?\x90\x83\\`\xa2A\xb2ܷ\xaa\x1e\xa1Þ\x8a\xf71T\xe4ݬfR\xa1\xfd)Th'CP|\xee\xc0\x86\xef$F\xb3\x9b\x83\x1c\xed ƶe\x91\xfd\xb4\x13\xe6\xb40\x94\xff?\x86=#\x11\xfd/)(\x93jJ.\xdc\r\x95\x1d\xdfm\xbe\xe1t\x9d&p\x03\x97)bvaE3\xb0\x85\x8a)'\xb0\xb7\xfc\x8a\x98oI\xcb3\xf2\xb0\x14\n%C\x1dDzv\x0f\xebgg\xad\x13\xb2\x03\xa2y\xf8\x8a?;\xab\xe2e\xadCY\xc9)\fa<ÿ=\x9bn\t\xd8\x1d\xb0\x0f\x88ݽT\xb2珕\xd6\xfdƦ6m\xef|_\xfa\xd8K\x1b[\x15\x18\x9b\xdfl\x11GS9n\x99\x15]\x9f\xa4r\x01\xba\xcb\x04q\x1a3\xa62L\xc9\x05_o\xc1ŋq\x9d*\xb73\xe2*:+Z티\xa5%fH4@\xb9\xc4%\xd5m\b\x9b\a\xb7wmϦ\b\xd9\xd2w\x0fY\x1co7\x1e\xb7\xa9\xa8V\xe3ۯ?w\xa9\xceL/#\xf5g\u007f\x83\xab\x03ju\x89^/a]\xe1\xf3\xbf\x04\xe3ub\xe0\xdbw\xd5\xf9\x9an\x98\x02\x9d\rS\x1f \xcb\bU\xdb\xcbw\x8d\x86\x121\x01#\xb4\xccNzzp\xa5\xb5\xcf\xf0\fv\x19\xa8U[\x9d\xbc\xd9\x1f\xaa\xbf\x11\xb5_õ\xca8\xfe\xf6\xcf\x12\xe4\x1a\v\x0e\xd4*Oe\xd0u\x9fq\xcb)\xb0\x05\xa8\xe7]\x8e\x01\x1a~\xb3\xa5\xf9\xd7\x1c\x83\\p+\x83;\xc1n\xcc\x11\xe1\x80jZ;\x86?\x1bCfǣ\x9dP\xb9\xa8\xde\ue987\xbd\xa2\xa6\x9f\xe5\xf3ԶO\xb8\xf5sP\xefx\x12\v(\xde\x06\xda\x03\xd2\xc8\xc0\xc3VP\xdfD\xa6\x03\x96\xd0\xd3\xd9B\x87\xac\xa1\xdej`\x1f\x8b(\xd2&:\xb8\x80\xa7\xb0\x8a\xc2\xec\xa2\xdeh:l\x1b=\x91u\xf4\x84\xf6\xd1SXHq6\xd2\x01\x90\x95\x05\xd5\xd7J\xea\x99b\xd9;D\xd1'\nt8n\xb5\xcf^\xeaa1\xf5\n~\x1c\x9a\xe9A\xbb)\xccr\xea\x85\xc3'\xb2\x9e\x9e\xc8~z\n\v\xeaim\xa8\x83V\xd4A\xca\xd9\xfb\xe7h\x1f9\n\a\xb9\x82k\x91\u008d\x90]\xf9\xdc\xed\xfc\xac\xcd\xe7;\"X\r#Hd)ޫ\xc5G;\x16\x85\xba\xbc\xd3\xe3\xe3\x16\xd5\x1dlr߿y\u007fh=\xef\xaa\a\xf7/\x84b/=k\x9fu\xacüo\xef\xd6sZ\xa8\xa5\xd0\xe4\xd4\x17\xb1J2Q\xa6\xce\b\x91\x1d\xf9]\x03V\xa9\x92%\xa4e\x06\xddMƷ\xca\xd2\xfbG\xbd~Sr\xf6\xcf\x12\x9a50\xab\x88\xb4{\xba\x8b\fk\x9cT\xa1\xb4F\x06\x859:\u007f\xc1\xfd\xf4_rQ#\ay\xc7\xd5\xd7&H\xcb#\x84\xd2X\x97\x80\xebF\x91e\x1ffJ\\;>\xf7xgY\r\xbf\x86]\xe6o\a;\xec\x16\x0f\x13\xf7խ\f\xd8\x1d'\xd2ޝm\xc3袹[{\xc76\xa1\x85.\xa5\x8b\v$\xa5\xc4\xfe\xbfu\xcbB\xea1\xe7P\xd4\x02\xbb[\x01vy\x00L\xf0;\x96\x83\xd24/\x0ePȫ\xed7\xcc\x06\b\x99\xaa\xaa\xb2a3$X7\xd9\xed2\x90i\xdd\xda9\x9d6`[0\xa8_\x18А\x12X\x01'\xeeR?f\xdaڀc\a\xd0;T\xc0\xe5\ns\u007f<\x1c\xbc\xdf7\x17\x92`\x17\xedj\xea\xdb\x14\xe1KE\xa5Tä\xb3rH\xaf\x93\xd8)E\xf1Z\xee!V\x83w\x9d\x9d@M\xf0^\x88\xd9\xde,\xb3o\xfb\x9bƮ\xb4\xc7\x03H \v\xe0\x06ŝ\x1cǩe\xb6\xb5\xabA\xac;\xc1U\xc0\xf6\xcev\xc3-\xa9\xfb\x80U\xd4+/R\x97\a\x02)\x19\x1f鬪\xb0\xaf`\x96\xbb\xe1\xfd\x0e\xa8꺧\xd0B\xc4\xd7\xcdg\x9d\xf6mq\x80KO\xa8틽\x04\x02\\3\t\x9d\xa4\xef\xa6$\xf0\xcb\x01g\x9c\x90bI\xd5!vyc\x9e\xa9Z\xf06\x0ee\xc5)\xdf\xed\x98\x13\xf02\xdf\x06>!\xd7\xf0\xd0\xf1\xeb\xd7H\xf4hQu\x1f\xa5\t\xb9\xe27R,dWW\x88\x89?X\x1d\x142!7TjF\xb3l\xfduw\xf7I\xff\xf5 ܹ\xa9\x1c\xd4\x12\xecc\xb5\xd2ĸ=\u007f\x86R\xe9\f\xbb\xbb\xd6\xc4z\xa2j:\xee\xf6\xd8 \xb4\xa91\xaa\xc0\x1b\xe3\xac\r\x14\xaf\\(=\x81\xf9\\Hm\x95\xb4Ʉ\xb0\xb9\xe3\x9f]\xca\ae\x19\xbalm\xd2\x1ca\xba\x0e\bU\x02\xc9\xd8\xfa|M$\x12+\xb6\xfa\xcd\xe9ڦ\xdc\xd0$)\xcd\xf1geNY\xb7\xde|\xa8\x88\x1e\xd6@\xb9\xdam\xe8\xb5\x13쪇\xfd\x02l\t\x95\xade\x88\xa6K|w\xfa\x00S\xfeU\xb3g\xc9\x12+h\xeb\xa5\x14\xe5b\xe9Ip\x17\x03\xdde'\x95X\xe4\xa7\xc8ʅ!k\xe7\xd4ҥ\xe4\r\x9b̹\xb9\xd2z\xba\xfb\x80\xeeG\xe1\x1e\xb5_\xb5$\xde!\x05\xb0\xf5\xf00\xc9^\x95\xb7\xfat%\xf2\xaab\xa9\x97}d\xf3\xfb\x8d\xc77\x12\xa7\x8c\x94\xae!:yځ\x9cS6\xb7\x9e\xc1\xc4\xccz;Y\xff\x03'@=P\xc9\x19_\x1cZ\xfc\xf7\xee\xb1\x0e\xd5\xc4A\xe8PN:\x16Q\xa9+Aʉ\x9f\xe4\x8e\xdc\xfeJa\x19\xa0\x9et\x9e\xa1\xad\x1f\x91\x90\xd3\x06\x92ݗ\xdc/\xb5Zo\xcbڹ\xc4D\x8b\xdb{\xc6ӗ\xfe\x02P\x91\x95\x92f\ue7c9\xe0\x96-\xa8\x97\xe4\x87\x1f\xbf\xf0\vz\x0fRU?\xfe\xbf\x00\x00\x00\xff\xff\a{y+\x88\xf9\x01\x00"), + []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec\xbd}s#\xb7\x910\xfe\xbf?\x05j\xe3\xfaI{\x11)or\xc9\xefn+\xf5\xa4\x94]\xd9Q٫U\xad\x94\xf5\x93r|>p\xa6I\xe24\x03L\x00\f%\xde\xf9\xbe\xfbSh\x00\xf3B\x0e\xc9\x01\x86\xda\x17{pU\x17/5\xd3\x034\x1a\xfd\x8enZ\xb0\xf7 \x15\x13\xfc%\xa1\x05\x83G\r\xdc\xfcKM\xef\xffMM\x998_\xbd\xf8\xe2\x9e\xf1\xf4%yU*-\xf2w\xa0D)\x13x\rsƙf\x82\u007f\x91\x83\xa6)\xd5\xf4\xe5\x17\x84P΅\xa6\xe6ge\xfeIH\"\xb8\x96\"\xcb@N\x16\xc0\xa7\xf7\xe5\ff%\xcbR\x90\b\xdc\u007fz\xf5\xd5\xf4\xff\x9f~\xf5\x05!\x89\x04|\xfd\x8e\xe5\xa04͋\x97\x84\x97Y\xf6\x05!\x9c\xe6\xf0\x92HPZHP\xd3\x15d Ŕ\x89/T\x01\x89\xf9\xd8B\x8a\xb2xI\xea?\xd8w\xdcD\xec\"\xde\xd9\xd7\xf1\x97\x8c)\xfdm\xf3\xd7\xef\x98\xd2\xf8\x97\"+%\xcd\xea\x8fᏊ\xf1E\x99QY\xfd\xfc\x05!*\x11\x05\xbc$\xd7\xe63\x05M \xfd\x82\x10\xb7&\xfc\xec\xc4\xcdz\xf5\u0082H\x96\x90S;\x1fBD\x01\xfc\xe2\xe6\xea\xfd\xefo[?\x13\x92\x82J$+4b\xc6͍0E(y\x8fk3\x13\xc0M zI5\x91PHP\xc0\xb5\"z\t\x84\x16E\xc6\x12Db\x05\x91\x101\xaf\xdeRd.E^C\x9b\xd1\xe4\xbe,\x88\x16\x84\x12M\xe5\x024\xf9\xb6\x9c\x81\xe4\xa0A\x91$+\x95\x069\xad`\x15R\x14 5\U000c8d63AG\x8d_7\xd6rb\x96k\x9f\"\xa9! \xb0Sv(\x83\xd4a\xc8\xccV/\x99\xaa\x97\xb6\xb9\x1c\xb7$ʉ\x98\xfd\x17$zJnA\x1a0D-E\x99\xa5\x86\xeeV \rr\x12\xb1\xe0\xec\xbf+\xd8\xca,\xd4|4\xa3\x1a\xdc~׃q\r\x92ӌ\xachV\xc2\x19\xa1<%9]\x13\t\xe6+\xa4\xe4\rx\xf8\x88\x9a\x927\xb8=|.^\x92\xa5օzy~\xbe`ڟ\x9fD\xe4yə^\x9f\xe3Q`\xb3R\v\xa9\xceSXAv\xae\xd8bBe\xb2d\x1a\x12]J8\xa7\x05\x9b\xe0\xd49\x9e\xa1i\x9e\xfe\xa6ڶ\x93\xd6\\\xf5\xdaP\x9eҒ\xf1E\xe3\x0fH\xe6{v\xc0\x10\xbc\xa5%\xfb\xaa]E\x8dh\xf3\x93\xc1λ\xcbۻ&\x9d1\xb5\x89}\xc4{\x83\xf8\xea-0\bc|\x0e\xd2n\"R\x9b\x81\t<-\x04\xe3\x1a\xff\x91d\f\xf8&\xfaU9˙6\xfb\xfe\xcf\x12\x94!h1%\xaf\x90\xa9\x90\x19\x90\xb2H\xa9\x86tJ\xae8yEs\xc8^Q\x05O\xbe\x01\x06\xd3jb\x10\xdbo\v\x9a\xfcp\xf3a\x8b\xb5\xc6\x1f<\xf3ڱ_\xee\xf4\xdf\x16\x90\xb4N\x8cy\x8d\xcd\xdd1's![\xcc\xc1\xbc2m\x01\xed>\xb4f\xd8\xd3o8\xd8\xe6_6\xa6\xf2\x97\xeaAC?f\x12%g\xff,\x01Y\x9c=\xb1\xb0\xc5R\xb6@\x12??$\x8b\xe9\xd6\xdfw\xe0\xd4\fxL\xb22\x85\xb4\xe2\xb6[k٘\xf1\xe5\xd6\v(\x8e(\xe3\x86\xfe\r\xfb7\xd3\xe6\xf5_\r;\xed\x981\x95@\f\x052n\xe1\x11\xc6q\xb1\x9d\x986\x83i\xc8;&\xb7wu\x04\xe5\x1c\x9de\xf0\x92hY\xc2\x0e\xccP)\xe9z\ab\xbcl\ue2d7\xeay\xc7\x102\x96@SPX\xd4X!C\xe5\xf6\x8c\xc8'\x8e\x15\xa6\f;\xf3\xab\xbc\x11\x19K\xd6\aQ\xd3\xf5\x92?n\xee\xf0y\n\x9e\xc1\x92\xae\x98(eǚ̑4\xcf\xdeג\xb4\xe6\xa6\xc203\a%\x8d[q'\xb6\x96B\xdc\x1f\xda\xfc\xbf\x9agj\xb6M\x12T\xeb\xfcZ\xa4\xdbn'Eg@\xe0\x11\x92RwL\x93\x90\xb4D\t\"$)\x84һ7~7\xf3!\x96\x1f\xec\xa2Z\xb2\x8fj\xb6V\xe6x\xa5\xdf:\xb3\xd0\x16\xdf\x14\x1c\xcc\\s\xb3u\xf5\xb3R\x94\xf6\xd9M\x01\xd7\xc0x7FȌ*H\x89pd_f\xa0ܷR\xdc\xfe\x9a\xb1\x9c\xed\x04]-ު\x1a\x19\x9dAF\x14d\x90h!\xb71\xd9\a\x9fv\xf4a\x96;\xf0\xd8\xc16\xdb\xf4_/l\x0fHb\xc8\xfcaɒ\xa5\xd5\x02\fm\"\x1c\x92\nP\xc89\x8c\xa6\xba\u07b5Hrh\xef\xddG\xf6\xf1\x8ez\x1c8S\x9b\xf0\xba\xf8I=z\xf0\xdbz\x1c\xe0\xbc[\x9c\xc5\xfd\xde):\xeb\xf1\xcbD\xac\x17%\x11D{\xb5\xf5\xeaq\x89\x16\xad*\xa3\xed_\xcd\t\xe4\x85^\x9f\x11\xa6\xfd\xaf\x87 \xd2,k|\xff3ޘp\x8a\xbf\xda|\xf3\xa8\x14\xbfwW\x0eA4\xbbR}\xfe3\xdc\x14\x14\x16\xb7NV\xf4ސ\xef\x9ao\x9d\x116\xaf6$=#s\x96i\x90\x1b;3\xe8\xbc\x1c\x03\x19}\xe4\x9d\x199\xd5\xc9\xf2\xf2\xd1h6\xaa\xf6@\xf5\xc4\xcb\xe6\xcbV'\xf6FB[0\x1f\x80K\xd0~e\x12rk\x17\xdf!6\xeb_Р\xb8\xb8~\r\xe9>\xf4\x90~\x94\xb7\xb5\x90\x8b\x8d\xc96?\xed\x14\xfd\xbe\xcbp\xaaOe4Y\x8f\xc7\x19\xa1\xe4\x1e\xd6Vc\xa1\x9c\x98͡\x1a\xf5\xddN\xf3i\x1b9\xe8z\xb1\xea1\xac\x11\x8c\xf3\xa5\x1c|\xbb/)\xd8q\x0f\x1d\xfa~\xd7h!\xd0\xcc\xc9Y\xb8\x16\x93\xe6\aD\x04Z\xde\xfd\x91G\xd0/\xe6y\xd1\xe1ő\xfe\x8c\xc4\x0f\x8f\xfb\x88eV\xdb\xd6\xf0\x1f\xe2ƞ(\xbbE\xe6\x14,Y\xd1s\xa1\xe8>T\x80\xa7\xc5{\xc6\xdeӌ\xa5Շ,\xdd_\xf1\xdd\xdap{\\\v}\xc5ϬI\xa6\x90J^\vP\xd7B\xe3/O\x82N;\xf1\bd\xda\x17\xf1xq˶\r\x1e\x9a.\xb6\x1e\xc4mǕ\xf5\xa4T\xdb\xc3\x14\xb9\xe2\xc6pq\xf8@\x87\xa9\xfd\xdc~\xf9\xd0\x1ey\xa9Ї\xc6\x05\x9f\xa0\xa8\x9cv}\xc9\"\xbb'H![;\xb2=\xb5\xea\xa3\xf6\x83=\xc1\xde\x19Ib߷.\xe0\x8c&\x90zk\x13\x1d\x97TÂ%$\a\xb9\xd8'8\x9a\xa30\xfc\xbd\xdf\x14zr];\x02)\xac\x9fh\xf7ñ\xee\xf4\xf0d&\xe6\xe4\xf6x\xcao\xf6\xc1Gw\xf8+w?zxE(bQ\xff8\x88]\x9a\xa6\x18\\\xa2\xd9M\x00\xc7\x0f؋m\xd9o'f%dN\vs~\xffLj9$\xe8\xff%\x05e\xb2\xc7\x19\xbe\xc08Q\x06\xadw\x9dg\xac\xf9\x19\xf3\x05\xa6\x88\xd9\xdf\x15Ͷ=\xe1\x1d\x8b\x13\x86\xb7@f\x05\xb9\x98oi,g\xe4a)\x94\x95\xa9s\x06Y\x97˦=\x98\"\xcf\xeea\xfd\xecl\x8b\x0f<\xbb\xe2Ϭ\x80\x0ff7\x95\xb6 x\xb6&\xcf\xf0\xddgC\x94\xa0\x9e\x94\xd8\xeb1\xde\xe9\xe7\xaeG\x8b,\x9a\xbe\xee\xda\xc9\xed\xd4\xdc}\xb3\xeeE\x87\x85P\xfa\xaf\xdd\x0e\xbb\x1d\xf3\xb9\xf1o\xb4u\xd3\x0e\xbf\xd7A\x9d\xdd\xf9\xb0*\xa6j4\xb9\xb9\x06\xe9\x9cx\x96\xd1z\v`\xa0mt\xc8IW9\xe8h\xe5Y5\b>@\x156\xe6\xd1g\x8a!Z\xa3\xc1K\xa0\xbe}\xf9\xd8\xf01\x9a\x13j\xfe\xdd\\ȱ\xb5\xdaD\xe49\u074c\xf2\xf5\x9a\xea+\xfb\xa6\xa7i\a\xc8\xee\xbe\\\x94x.\xfb\xab{\x9e\x860\xbe\xf7\xc0\xf4\x92qB\xfd\xf1\a\xe9\b\x8a\x92B\x1c\xe6Dv,\xa9\"3\x00^\xf9\xc6?\x05y\x9d3~\x85\x1f /\x8e.\xdfI\x8d\xae\xa8\xed\xf4\xa8\xae6\xb4\xfa\x01%N_\xd5H\xa4\xe4a\t\x12ZT\xb1\xed\xf06\x1acO\x90\\\xe8\xa6_\xc1\xc0-Dz\xa2ȜI\xa5\x9b\x13\xedKp\xa5\xeaK\x0e\x81;lVw\xc7r\x10\xa5\x8e\u0603\xcb\xfa\xedV\x806\xa7\x8f,/sBsQ\xf6\x10\xeev\x18\xf9\xc2\xf2*\x8a\xeav\xe0\x812]œ\xd0â\x85٥\"\x03\xddw\x8bg07\xec(\x11\\\xb1\x14\xa4\x8f\xf2\u06dde\xc2\x1c\xdc9eY\xd9\x15\xbe\xe9\x1a\xa1f*\xbf\x942\xcaJ}k\xdflx\r\x97⡍\xa0\xde(X\xd2\x15\x106'L\x13\xe0\x89\xd9\x17\x90\x96e\xe3'\x1c2\x105\xbdɲ\x1f\x837\x03x\x99\xf7C\xc0\x04O6\xe3{\x9db\xcdǿ\xa6,{\x8am3\x94\x17\u007f4\xbe\xaf\xdf\xfe G\xa3b*\xfdE\xd8\f\xc8;\xa0\xe9ڟ\x0f\xaa\xb51U\x91\x06\x04\x91%or\xc4'8\x19!\xf6\x9d\x9b\xc51\r7\xc6Y\x8f\x8d\xdd\xf0\xe73\xdd\xd4v\f\x88'\xd5v\xcc\a*A\x17㚹j\x010\xa2\xd2+\xce8\xf7\x8aj\x024\x9f\x19\x18\x03\x15R\xeb\xf42\xe2\xd3\xe9\xd16wiG\x18\xbcsu!\xaaˆ\x9b\xd7\x19\x9a\x8d|\xbf\xe0#\xe0\x1c\xbckQ\x92\aʵ'\xfaJ\x99+DO\xaa\x0f\xddU;\xa8\\\x04<\xbd\x95L\xe8UV\x9f\xd1\a\\\xcb5f\x98\xf5\x9d\xb4\x1d\xc64MEroԑ\x9c.\xe0\xe4D\x91Wo^\x1bR1Z\x87\x11\x19\x01\x12\xc1\x0ef#\xb1\x85\x14+\x96\x1a\xd5\xe9=\x95\x8c\xce2c\x04\xcfA\x02O@\x91/O\xdf_\xbc\xfb\xe9\xfa\xe2\xcd\xe5\xf3 \xe0\xc6t\x86ǂrC\x83\xa5\xf2Ҽ\xda}\xb3\x00\xe0+&\x057\b\n\xc3\xc6՜P\xb2\xf2\xb3M\xaa\xe4;cje+\xa7\xcd\x05A\xacV\xec\x1d!\x8c\x17\xa5\xf6\xde\xd1\a\x96ed\x16\x06\xb1\xe4ɒ\xf2\x85\xc1\xebkQ\x9ay~\xf9%bEBZ&\xee`\x06At\x87\xe9\xcb3\x17\u03a2Y&\x1e\x14\xca\x16P\t-\x1c\x8e\x83`6\xb6\x97\xa85\xd7\xf4\xf1%aS\x98\x92g_6\xfe\xf4,\b&b\xab\x90\xc2,\xd3\xc6#,\x163\xa6AҌ\xa1\x13\xb5\x84,;\t\x98e\x90\xb8\xb0#\xd8\xdem\xbe\x16\x12`\btL\xd8\xd1\xe6\xe8\x97\x15\x03\xb7_\x9e\x92k\xa1\xf7e\xa0\xed\x1e\x95\bC\x1cO;y\xfc\xe5\xf5ݻ\xbf\u07fc\xbd\xba\xbe\ve\xedM\xb1\xb0\x9b\xd5\xc71ɖX\xe8`\xf5a\xbb\xbfO,\xb4Y}\x10\xdc\x1dba\x8bՇ!\xb6C,l\xb3\xfa0\x16\xbc-\x16v\xb0\xfa \xb0\x9bba'\xab\x0f\x82\xda\x16\v\xbbX}\x10\xc8n\xb1\xd0\xc1\xeaÅжXh\xb3\xfa0\x88\xbb\xc5\xc2\x06\xab\x0f\x02\xdb-\x16FV\xdf\xf1Z\x18\xab\a\xbe\x8af\xf3\xdf9\xf3\xab\xc1\x8a\xaa=\x0f\xa3C-0\xe3\x80\xf16\x9f\xeb\xd2\n\x9e\x16\xf3m\x97 _\xbd\xa7\xed\xb4\n\xde\\l\x10dR\x1f\a\x9f\xb1\x8db\xad\xb2h\xc3XL\x8c\x95fǡ\xc8Y\xf7؎\xa7\xb9\x8b\"\xf1\xf8 \r\x9cL\xc9\x1b\x97a@ɫ\x9f\xae^_^\xdf]}}u\xf9.\f)$\xfe\xec\x10\x9f42\x105'\x1d\xe6a\x04^\xf6k\x0e\xc1\x02َB\u008a\x89Re\xeb*\xbd}\xf8ѵc\xf3五\xb25Q W,\x89\x99m\xe7Ԇ\xa8:v\x1cTx\xe2W\u007f@\xed\x89\x00\xbc\xdb&v\xcaO\fi\x1d\xd32v \x9f\xc0>\xb6〕\x1c\x01\xf1\xb8\nTc\x96{ը\b\xa0\xfbml\xd2;q\xb19P\xfdz\rsZf\xd6\xdb\xf6\xec\xd94D\x97\xb1c(\x8b\xfdZ\x8a\x9e\x01\x94\xe6h\xb1\xd9[{\x01\xcbG\f\x8e#\x84N\\blK\xedP\x81\xf6\xaa\x1d\xcc\xe5Nz\x9b2(o\xae\x1e\xf1R\x9eؐ\xf4\x9c-\xde\xd0\xe2[X\xbf\x83y\f\x88M\xb4cάK/\r5\r\xea\x81Z\x8f\x9dZ\fW\x1c\x8a\x17\x12\x92Q\xdc5Z8\xb9s\xd9Ϩ\xc3\x1a\xf4\xc4-\x89\f;X~\xc4iw~\xb4U\x99\x86\x9a\x17\r\xb1\xf2\x87辆[\"x\x02\x85V\xe7bet\ax8\u007f\x10\xf2\xdeXb\x0fL/'6\x1e\xa6\xce\xf1\x1a\xce\xf9o\xf0\u007f\x06\xcc\xee\xee\xed\xeb\xb7/\xc9E\x9a\x12\x81\xac\xb6T0/3\x9bv\xd7;ӷk\xd4u\x14\xce\xf0.\xff\x19)Y\xfa\xe7pf\xeb\xc7\x11hC\x146\x13\xf3H\xf4q\x8b\x91\xfc\xb5\x97R\x03peXx\xc5\x11\x88\x90\x18~\xeb\x93\x06\xbb{\xf8\x84e\xa7\xe8\x0eD\xfbL\x88\f\xe8f݊~\xa3\u007fh\xb8k\xf4K\a\xee\x1a\x01\xe1㮁'\xe08R\xe3\xa4\x16\x1b\xfd\xd2Y\xbb\x8738\v\x91\xbe$\xaa,\n!\xb5\xaaj4L\r#\b\x8bgԣ\x05\x04\xef\xf6\x9d\x91\xff\xac~Ļ#ꇓ\x93?}{\xf9\xf7\xffsr\xf2\xe3\u007f\xc6~\xa7\x86\xd9(\xafs\f\xc0\xaa\x80d\xcaE\n\x86e\x9f\xd9\u007f:\xcb\xeb\"\xc1\x04\x99\xeb\x01\xe8Q\x9a\xeaRM\x97B髛3\xff\xcfB\xa4W7\x03A\"\f\x15\xa1\x82\x92\xa3(\x01\xbbj݄\x8c\x16\xa5\xfb\x9a8\x83\x85\xa6+\x9fc\xe8\xfdksdn\xa8^\xf6O\xb1\xeb\x1a\x0f\x92i\r\x1cmU\x90\xb9\"b~f\xb8#\x9a\x02Cx\xb7 \xcfV/\x02#\x94-\x00\xc3\x05\xdbܣ\xe8Hۈ\xd8v\xecf\b\xc7\"\u07b5i؟\xf7\x12Tٔ\x03\x80^\xdc\\\xf9ZK\x1f\x11\xf1C%[\xb5m\x1fC\xbe\xf9\x84\xf3\xaf\x9fD\xcey\xe8\xc3D]\x9dSl\xef`\xf4\xbbɻ{d\f\x8b2Q\x9eօ\x99N\xed\x8fӤ(c\x99\xb9\x83\x90C.\xe4\xfa\xcc\xff\x13\x8a%\xe4 i6QZH\xba\x88\x16?~\xaa8\xc5\xfa_\xf6s\xb1\x9c\xbf\x81\x82홆%\xf14\xa0J I)\x8d\xb5\x93\xad\xbd\x8e\x02\xe9G\x93o\x15\xfdtW\x85\xea;\xdaD^'\xab\x0f\xb35k\xfe\x81n\x9c\x95\xc8\xca\x1c\xd4Ye\xa5\f\x00\x8c.M\xbe\"+*\xd5G\xb5\xb8R\xb6b\xaao\xbatנ|\xfd6\x925\x11\xe4\xb1v\x11\x8ckX\f0\xd1&\xc7@F\xa7\xf9\xe8\xcaG\f\xd8lQ\xea\xa2\xc4\xe4\xe1\x9c\xea**\xf5X\x888ϝ\x1f\x8d\x82>i\xd3a\xfa\"ƍmGA\xb5\x06\xc9_\x92\xff8\xfd\xc7o\u007f\x9e<\xff\xf3\xe9\xe9\x0f_M\xfe\xfd\xc7ߞ\xfec\x8a\xff\xf1/\xcf\xff\xfc\xfcg\xff\x8f\xdf>\u007f~z\xfa÷o\xbe\xb9\xbb\xb9\xfc\x91=\xff\xf9\a^\xe6\xf7\xf6_?\x9f\xfe\x00\x97?\xf6\x04\xf2\xfc\xf9\x9f\xbf\x8c\x9e\xf2\xe3\xa4\xf6\xd0L\x18\xd7\x13!'\x96\b\x0e\x16{\xd87\xa57\x1e\x8c!\xff\x84f\x19\xa4\x84\xe59\xa4\x8cj\xc8\xc2\xfd\xe4\xbe\x02h\xb3ܣ\xed\xf0i\x8bIF\xe9\rK\xca\xd3\f$\xd6+t>\xc0\x16|\r2g\x9c\x86\x16\f!Uz\x17\xba,!%4I\x84L]-8_ً\xcap\x8d\xbf\xe2x\xa8+5$\xcff\xbe^0\xe4Y&\x92{EJ\xaeYV\x97\x87\xf4\xb5!]o\xca`\xa8Q,\xa6\xfa\xcfIu&&؏\xec\xfc7\xf5\x9f\xf0\x87P\xe5w\x88\xe5ӯ\x9e\xef\xf6بA\tH\x1a\x98L)\xc2Ŗ\x1f\x98\x17,\x8c\xfab\x88\xaa\xae\xafZ\t\x9a8#\x03\v\x10\xb7\xbb\xeaPd\x9bX\x17\x8d\xde\aV!\xb1ch\x8eBD-\xa0\xe6\xd8S\xb68:\xd6\xe8\v\xdbf\x8cC\xb3~1Ú\xa8\xf1!\xcc\xe6\t\xb6\xfc\xc8Y\xa8\xf1A`&\xb1\xc7ȺQ\xdb\xd2\xce}H2\xbf\x14B\x93ӓ\xf3\x93\xe7[A\xad\x93x\xa8s\x96\x81\x95\xae\xb6\xc8RRmV4H\xc5\xf2\"[\xe3\xfe\x9c\xa4\xd8\xd1\xc9]\x87\x95e\\\x8c\x98 S3\xbb\xec\vB\x9d\x11%\x88\x96\xd4w\x19\x88\x9f\xab\x81f\x80kY:]\xe5\xf4\xe4\xe7\x933\x02:\x89\xcd\a&\xe4A\xf0\x13\x8dd4%w\x82\x94\xaa\x9ex4̵(\t\a[\a\x00\x1e\x8b\x8c%Lgk\x14\xf3\xd10E\xa9m\xf1El\x90\x88\x85\xb6.\x1f\x99v\xf7t\xe2\xc1\xce\xc9Wxڭ\xaa@\xa81\x86Vp\xbe\x04\x9a\xe9e\xfc\xfd>C\x97\\\xf0\xc9\u007f\x83\x14XƋ;\x88\xb1ޝ\x88\xd8Ys\x1c!\xe3$ƍ\xb0\xf9vd\x12\x83Q\x10\xbe\x81`\x95\x93lu$\xbd\xbb\xbb\xf9\x06t[\x84E\xa1\xc3\xcc\xc8\xe7\xe7\xa3K\x1b\xe4\\Ȏ.Ç\xc7P\xf9\xb7\x14*\n3d\xbb_\xabҶ\xfb\x845Rx\x9c\xcf\xd9\x0e-\xdai\xc9.\xa3\x91\\\xdd\xc4'b\xfd]\x94\x06[3:\xcb\xd6U\x15Y\x05\x9a<3S\x8fO{f\x1c\xf7\xf3\xaf@S\xac\xdb˕\x06\x1a\xa9\"\x1d\xe1\xa85\xe6r\x1c\xa5\xc6\xf6\xdd]Z\x90\x03v\xb4Y\x02\xcb\xd1\xfe\x14\xcfT<\x9b\xb4\x15^$\x14\x96\xfd\xba9~$&\xb9\xc5+\xec.\xb8\xdfg\x83r\x13\xa9o\u007fl\x97\xe8j;G\x16\xef\xf0\x83q\x9c&\x1e\x8a\x01\xb3\x1b\x9e%L\x06g\xab\x92\xae\b\x98\xc5\xd5 \x98\xee\xeeexZ\xda\xe68\xca\xfd\x92\xe8\x12^\xcd\xf1\x94h\xc2\xe9}|<\rK\xb5$q\x89\x88\xedׇab\xe0\r\x052X\xdf\xc2\xcb<\xd1\u05cd\xb7/\x1bkAh\x92\xc4\x15\x8a\xb2\xc3u/G\x86\xa5@\xaeB\x13\x1c\xeb1\x98\xc4\n\x11\xee\xbf\xf4cЅ\xb7\xe3\\w;\xcae\xb7\x8ez\x89\x92\xf02\x9f\r\xe0$U\x01\f\xa9k\x82q\x1b?\xc0\x99R\x15ۼ\xc6\xe9\xf9\x10\xee\x10}\x0fU\x18\xca\x17@^\x98\x99\xfe\xf1\x0f\u007f\xf8\xfd\x1f\xa6\x88\x86h\xa8>\xb0L9\xb9\xba\xb8\xbe\xf8\xe9\xf6\xfd+,\xe2\x16K\xe5Or\xb3\r\xcb6D˟vd\x1eA\x19\xec\x95\n\v\x9d\r\xd9ack8\xff\xb7u.\xab\xd88[sh\x81\xec\xe6#\xf1\x99!Bl\x82\x87\xe8C\xdb\xd9:)nEr\u007f\x04K\xfb\xe4\xeeՍ\x05U\x1b\xdbQ\xbb@\xb9w13\xbe\x12\xd9\xca\xf6\v\xbc{u\x83\b\x8a\xdbY\xf36\xc6\a\xd0շ6s\xf47\xe1mjN\x14T\x96\x17\xaec&%\x12hƔf\t~\xab\nSD\xda\xf7\xe2>&\x8b\xe7\x93\xf1+\x9c\xbc\xf5\xe9@\xe8b\x88>\xcd\x1b\xae\x89\x96\x8ba\b\x8bh\xb8&b\xaft\x8d\x1a\xc9\xd15\x12+\xea\x85\x1c\xa6Ǐ\x1aɧ\xad\x91|n22\xfa\xd5B\u00ad\x16\xc5\xc0\xac\t\v\xe4H9\x13\xbe\x13ݮ\xa4\x06\x92Fl\xa9\xed\x1d}qsUy\xc7E+\x11\x01\x93W\x82\xa1\xaa2Y\xfa\xd8\f\a\xa5\xce1=\xa2,\xac\xe7\xcb7\x94\f\x8fX\x15\x12\xb0\v\x9f\xe0gUE\x02D\ap\xfb#\xe8$\xfc\xb4\xa0O\xc6厸x\xa2߮\xa1i\x18\x89\xa4j\tة\x02\x1e\x99V\xbe\xdb5U\x82\xdb\x10\xae\xdb>&\xc2\x03\x98L\x91\x82*e\x03w\xba^\x84\xfdȍHO\"\xa2\xb7\x8d\t\x91\x85\xa4\t\x90\x02$\x13)\xc1\xaa\u007f\xa9x\b\x9f\xe7\f\x16\x8c+O\xbff\xa2\xfe`\x18]\t\xa2\"\xc2u\xe7\xd9w\xad.Rخ\xbcԉ\x88\xe0\xc3\xeeu\x87\xc5\xcd\x04\xa2\u0ad38Ms|J\x9ae\xeb\xfa\xa0\xfa\x9b\x9e\xfa\xf8\x9b\xb4\x9dI\x14\x8b\x84zݛ\x99D\xe1\xd1\xc0V\xe6\x919\nuV\xd2\x10\xf2oQ'S\xe6T%\xcb\x01m\xbeHx\xfa\xf2\x98\xdatp\x8c\xa9M\xbdǘ\xda4\xa66\x8d\xa9McjӘ\xda\xd4\vĘ\xdaT\xcdhLm\xda3\xc6Ԧ1\xb5\xe9\xf0\x18S\x9b\xc6Ԧz\x8c\xa9M\xbdƘ\xda\xd4c\x8c\xa9Mcj\xd3\xce1\x06\x12\xc7Ԧ_c qLm\n{}Lm\n\x18cjӘ\xda\xe4ǘ\xda\x148F\x8ddLm\xfa5j$\x9f\x9b\x8c\x1cT],\xf05\x9f\xc7s#\xc5l@\x99\xb1\x1b\x8cճĥ\x01\x89ytm\x1d;\x9d)y\xd5J\xcfpM\xf8m\x95\x96 \x88.ѧNO\x1aZ\xaf'\xb8&\x93/\n\xa6\xce\va\xff_\x9dS\xd0H&\xb0\xfe\xb5\x10\xe1\x10+|c\xb2\b\x0ee\x10D\xf1\xba\xfd\xd9\x03\x98\t\x10\f\xf3\x98\x99\x03C\xb4\x9b\x01\x19\x03{\xb2\x05<\xd8(\xe6ڝ)\xb0\x11\xf1\x8fN\x05qY\x02\xdb\xd1\xfe!\t\x17\x98\n\xb7\x15鏄Xe\a\xec\x8a\xf2ǩ\xe4\xea\xf8\x11\xfe'\x88\xee\x1f?\xb2\xbf'\xaaO֢\x8c\x82\xb9#\xa2\xef\"\xf3\x91\xb4\xd9\x19\xcd\xf7Q\xf98\x98ݑ\xfcVD>\x96\x98\x06E\xf1\a\x04\xa7\x06*\xd7\xf1\x9e\xe4hM\xc9%\x1b\xdf-%\xa8\xa5Ȃym\x8bϾa\x9c\xe5en\u06042쑭\xaal\xe6p\x1a\xf1yNV\xeb\xb0a8\x03\x98\xa5\x80M,)\xcbbJ\xd5ai\xbd%E\xff\x84*\x93\x04 5r\xf2u\x1d\x02\x0f\x86\xf9\xfbi\xb5r\xdbU\x83)\xf2\"\x94\xf2lCE\xb4\xef~\xff\xbb\xa8ݏ\xb1\f#\x136\x0e'k \xe4`L\x0eO\xd4\x18\xa2n\xc4:R\x9e&9cOb\x06\xf9{\xa4hؓ\x94AX\x9c\x98=RB\xc6 \xce90\x11cO\x12\x86\xc3Q\xa4\x02\xb2\x9d\x80\xb1\x99H\x11\x87\xf2\xf8\xe4\x8b\x01\xb2\xed\xa9\x92.v'\\Ē$\x19\x9cl1<\xd1\xe2\x88\xdd\x0e\xeb́\xc1\xdd\xf1\a\xb9\xe8\x8e\xe09\x1c\x98T\xf1Th9F\n\xc1G\xec>\x1b\xbd\xabC\x92'\x06&N\fI\x9a\x88M\x98ؓ,1\xc4\xd3<0Qb\x10\xf9Ć#\xa2C\x11\xc3\xc3\x10\x83C\x10{\x12\"\x86\xf4\x84\xed\f=\xc4\xf6/\xf4\xa3\x1dv\xd8\b\x1fD\xaa\x85͐\xc3QC\aG\x0f\x1b\xc4'1\xecO`h$\"\xc4\xe2p;yaH\x12\xc2\x00\x8a\x8ee\xfeQA\x95h\xa6\xcd8ӌf\xaf!\xa3\xeb[H\x04O\x835\xa3\x8d\x86H\xd5yU\x16\x9c\xb5\xcc\xc33!Z\xb71\x97\xd4u΄\xd4_\xa8\xf5ѐp֊\xea#\xa1\x18\xa70\xab\xd7\xedۓ\x1f7nA>\x9a\xcb\xc0^)=\x06\x11\xfcU<\x101\xd7\xc0\xc9)\xe3\x9e\x0e\xc2\xfd\xa8\xb5\xb3\xa0\xf6\x17U\xc7\xda\xfc\xf5\xc5W\xe1\x9c\xcbN\xe6\xf3u\xec\xa0kK\xa9\xa7\xf3\xeb\xb9\x0f\x1c߱\xe7\x00\xcf\xcbp\x1f}˹g\x1d\x84m\xfe\x1e\xbcyu\x1b\xbe\x178o\xcfM\xd0K\xed\xca6D\xc0\xfcL\x89*:\xed\xec`\xca\x19\x89\xe8<\xb6/ݬN\x1d\v\x06\xbb#լN\x1b\v\x9f\xe8\xae4\xb3\xa8\x94\xb1\x8f\xee\xe1\xdcH\x13\x8b7?w\xa4\x889\xf5,R\x89\x8fN\x0f\x1b\xed\xb0\xc0\xb1'\rl\xb4\xc3>!;\xec\xf3\xb00\x1a\xb5N\xbe\x914\x81\x9b\xa3\xa9\x99\x9e]\x91\xb4\x94ԉ\f\xaf\xe0E\xd9\x1b\x86\xc9p\x80\xd4r\xaa\xaap\rV\\\x99\x97YD\xf1\xaa\xb2\x10\xbc]\xfd\xc9\xe6T4\x8b\xb8\x04\x03u\xd9.\x1d\xabv\x8aR\xcc\t-\xa4\xb0j\x1f\x91%\xe7F꺳d\x90bl%\x15'!\x9b5{\x14[\x98\xed2*\x16V\xc1a\x11\xf2\xe5a\t\xdck\x99n\xc2fvs!\x136\xcb\xd6dI\xb3\x98\xf0\xcb\x03\xd3KB\xc9=\xcb27\xcd)\xb9\x05M\xf4\x92\xa9Hgj&\xf8\x027\x83\xda\t\xc3c\x01\x89Q;\x92\f(/\x8b\xb8\xf5\x1beu-J\xe9\xd7\xef\xda\xc6\xf9Y\xc6$mp\x96\x9d\xf9\xad>Q\xfb\x0fl\x04bm\x82b\xa9\xc0\xd7iz`\nΆ`ַ\x19\xb5\xe7\xc0\xae\xbb\x90b\xc5RH\xc9l\x1dG\xff\"E\xaduJ\xde#<\xcf\xf7\xb9\xe0\x13\x0e\vjl\xa3\xf0\x93j\x85\xb8=\xf3v\x9e\xb6\x1e\x05OYBu\x84\x8d\xa5\xb0\xb0^]N\x8f\xac\x18E,4(7\x18\xe8)\x17D\xa0R\\r\xa6\xd7\x18\x1b]\x96\x9a\xa4\xe2\x81?\x9fb\xeb\xd9\x18&E\xc9\f4u\xf7Zm+A\x14X\x8a\x00\xa7\xb3,F9\xc1LܻN\x02%s\xa0\xba\x8c\xe8\uede0\x1a:\xfd\x01\x96\x1e\x8e{\x1c\x98r\x11\xd09)\xb9\x82\xe0\xfb3\r\xfb\xf0\x8f\xff\xfa\xe1\xecC\x96\x83(\xf5'\xe5 |X\xb2d\xd9\xf47\xb0\x1c\x14\x11\xe5\x90kkZ\x90\x17nZ\xdd\x14\xf1\xc4\xed#\u007fq^\xc5(\xad14\xc4\xde\x117ڬ\xe6W%N\a\xad\x9b\x1a\x1e\xf6\xfa\xfa\xf6\xa7\xef.\xfer\xf9ݔ\\\xd2d\xd9,C\xca\t5r#\b&ʕ%]\x01\xa1\xa4\xe4쟥\xed\xe0\x9e\xc4E\xa7&m].\xf0]O\x05a\xd6ِ\x8a\x02\xa1\x89έ\x10\xa0\xb1`&9-&\xf7\xb0\x0e\xd2y\xe3\xb1\x14\x85\xa3\xedI\xdb\xc5\xe7\xb4\xffM0\t4e\x9fP1\x05ǥ\xeayuWU\xc8\xc5*\xd0i\x84֞\x87\x0e<-\x04\xe3Zu\x95Z\b\x02\xbbm2~2)\x8bc\xa9\x85\x8e1\x96Z\xd89\xc6R\vc\xa9\x85\xb1\xd4\xc2Xj\xa1{\x8c\xa5\x16\xc6R\v\x9fU\xf2\xf4Xj\xa11\xc6R\v\x11c,\xb5\xb0k\x8c\xa5\x16z\x8d\xb1\xd4\xc2\xf6\x18K-t\x8e\xb1\xd4B\xc7\x18K-\xf4\x1dc\xa9\x85j\xfcr\xae\xf8\x8c\xa5\x16>\xd5+>c\xa9\x85>\xe3\xf3\xb8\b5\x96Z\x18K-x\xbc\x8c\xa5\x16\x82\xc6Xjac\x8c\xa5\x16>W\xa2\x1aK-\x8c\xa5\x16\xc6R\v\xdd\xdf\xfd\xb5\xdbac\xa9\x85O\xd5\x0e\xfb<,\x8c\xb1\xd4\xc2Xja,\xb50\x96Z\x18K-\x8c\xa5\x16\xc6R\vc\xa9\x85\xb1\xd4¯ȫ\x18\xa55JP\xa2\x94I\x98\x1d\xdc&\xb2W\"/J\r\xe4\x9d\aU)\xcbA\vGY\xc2T\xf3F\xff\x87\xedD\x98\b>g\v\xa7\xe8\x9d\xe7\x94\xd3\x05L*\xfcL\xea\xfbw\xe7\x1f\"7>c9\v+\xb2`F]\xb1\xe0f\x80\x87#Ҡ\x1ejN\x0f4\xa6\v\xaa5H\xfe\x92\xfc\xc7\xe9?~\xfb\xf3\xe4\xf9\x9fOO\u007f\xf8j\xf2\xef?\xfe\xf6\xf4\x1fS\xfc\x8f\u007fy\xfe\xe7\xe7?\xfb\u007f\xfc\xf6\xf9\xf3\xd3\xd3\x1f\xbe}\xf3\xcd\xdd\xcd\xe5\x8f\xec\xf9\xcf?\xf02\xbf\xb7\xff\xfa\xf9\xf4\a\xb8\xfc\xb1'\x90\xe7\xcf\xff\xfce\xf0T\x8fl\x9c\xb6\xcf\xe3wH9uJ\x11\xf2\xed\x9c>\x1a\x06\x1bN\n\xb9(\xb9\xb6\xb7l\xec1\xafN\x84M\xc3\n=\x94\xe4S9\x98d\x88\xa1\xed\xf2\xd1\xc6\xf3\x190\xc6\xf3i\xcf\xe7;G;\xed\x13\x1a<\xc7ܩL{Nh0L/\xb8\xd1Э\xe6\xc9\x14\x119\xd3Ɯ\x8e\xb9f\xdc(\xa4\x82WR\x9a.j˫µ\xbc\xb9\xbdM\xc1T\xf3\x82F\xe3R\xb8\xf0\xb6o\x8cZJy\x1d\xa7@\x9e3Ia\xce8\xa4V=\xfd\xf5\xf1\xbb\xa8\xd7\x14$\xa5dz\xfdJp\r\x8fA\x8e\xfd\xf6y\xb9m\x03\"v3\xc2\x0f\x8d\x9f\x10\x11\x85\xbdv\xb4Q!\fo\xfe\x85\xa9\xac@d\xc9џe\xeb\\\x80\xb6\xce\x1d4\xc3\xf1f\xcf\xc6\xe4\x83\xc0{\u05cb\xf5h\xfd\xb3d+\x9a\x01\xd7\r\xe87h\x1c7?\xf0\x14\x1a\xb2\xa6꾦J\x98\x18S\xa9\xc2۹G+\xfe\x04\x8f\xfa\x83hǨz\xdcH\xb6b\x19,\xe0R%4\xc3\xd32\xcc\\\xbe\xd8\x015\xf8\xc0\x1bTH\x91)\xf2\xb0\x04É\b\xf5.D,\xb2\xb0\xa0\x11Iٹ٫\xc2ONY_\xa7Q\xf4\n*\rUx\x1fe0`\xacE4\x13\"s7&\xb3u=\u007f\x16\x17\x82\xe2\xe2'\x0e\x0f?\x99\xd9*2\xcf\xe8\xa2rM*бi\xa2\xf5Q\xadܱG\xdb0\xa6P\xae\x13\x9a=е\xaa\x1d\xdfqW\xcb-ė\xe4\xc5s\xe4\x0fT\x91j\x8e)\xf9\xdds̰zuq\xf3\xd3\xed\xdfo\u007f\xbax\xfd\xe6\xea:\x8e\x8f\x9b=\x83\xc0\x98\u007fB\v:c\x19\x8bQ<\xb72Ǜ\xc0Pp\xa6\xe9y*E\xf8\x95%ķ\x8f\x85\xd4\xf2m\x98w\xa9Y\x11\x0e\xc9nޚp\xb8\xefRR\xae+\xa7w\x83\x1ce\xc95\xcb?\xe8\xa5n\x9a\x0e\xbf\xd0}\x91\xa6\x90\x0eC\xc9\xf1\xee¼\xf2\xd3X\xd7\x05颠\x12r\xf3\xf6\xf6\xea\xffn\xd0\xe6\xba\x18\x92\xa0\xff\x11\xee\xa2\x12b\x0e\xd2\xe0=~g\xebW\x8c\xbb\xbcw|~7\x8e+=`XN⻒\xb7\xcb\xd9\xd6p#\xf4\x93\x14\xa6䦊\x14\xb7\xa05\x98z8\xaf\x93@\fH\xae\x19ͲuS\x13\xd6\x02k2\x84\a5\xf9\x8e\xdc\xf59\xcdT0#\x8f\x97\xc6F\x91yc\xcc\xf7A\xbbXA!)p\xa1\x9d\xc7/\xea4\x889B#֧и,ВxQJf-\x8c\x99\xf28\xbf\xa9f\x8e\x11\xa6\xf0\x94\x0f\x05\x9bf\x9c\x13ƕ\x97!*\xe8/\x81\xa6XS\xa6\xa0zi\xf3Ts\xaa\xee!\xb5?D\xea\xd8UH\xd6̸Z\xfaݺ\x80\xe8x*\xea\xd66\xfb\x17\xe3\xbc\xe1\xde\xd8\x01\xe5\xbdh\xfa\x96g\xebwB诫2&\x83\b\xf9{g-\xb5\xe3@\xc1HYb\xd9n3\xbf\tn\"\x96miVZq\xd4\x17c%|`\x06!K~\xa1\xbe\x91\xa2\fV\x05\xb6\x94\xf5o\xae^#\xbf,]\x86\f\xd7r\x8d\xa5\xa9b\x98D\xfb\xccU\xf6\xd8\xdf\\NST\xb6M\xc5\x1e|\xb8\x9e\xbc\xa1kB3%\x9c\xe1\x18\x11\f\xee\xf2\x90\x10窉\xb9\x19=\x13z\xb9\xe9\xd3A\xf6\xb0\xfd\x9d\xf0\x02Fu\x82M\xe5\xc94K\x18\xe2BB\xb0\xf4\x1e\x14)$$\x90\x02O\x82\xa9\xf7\xe3\xa4A \xe5_\vn\xd8\xcb ڿ\xf2\xf9?\xd6e<̪\xc7L%g\xd3S\xccWB\xe6R*\x9069L\x96\x10\xb7\xf1ߖ3\xc8@[G\t\x16\xb9\xa5\xdaz\xfeXN\x17ᧉ\xeaJ\x14jA\x80\xabR\x82s\x9ak\x92\x8a\b3\xc0Ց2K\xff\xdb\xd5k\xf2\x1595k\u007f\x8e\xe4?\xa7,\x8b\xa9\xfa\x82\xb7?6\xb8\t\x9b\xfb)\x1a\x94\x86\xeb\x04\x1c\x8d}iY\xf5\x19Ⴈ2Yz\x9c\xc6x\x87\xbc\xf3\xcaݐ\xc2+l#k\xfa\x04X\xd3@\xc1\xfa7\x05r\xb0\\\xfd\xdb\a\x90\xabC\xdc`\x867\xb5w\r\x19\n\xc9AӔj\x1a\x13|+y\xa3:\xe2\xc6Q\x88\xa1\xdd\xfdG\x01I;\x18\xe6\xaf\xec(|\x1c)\xad\xe0;\xc6\xcbG{;`\xb8C\xf9\xf6\x12\xc1\x11\x17J\x8a\x91(3 \xb4(2f\xcb\xf7m\xb4\x88\xb9j\x91n\xdc\xdeo\x9b\x9a(\x1eh\x96\t\xa3fD\x84\xc7%\xe5\xa9ȷ\x16o\fQ\xa0\x11Vqc\xc1\x1d\x87s\xd7a\v\x97\xdd\xf5\xe1\xfc\xb5\x1d\xb6!\xae\xfb\fV\x10Q\xa5|\xb3\x89\x92\x81b\fRO5\b6\xca\xfb\x99\xd1\x19dV5\xb4'Gm\x9f\x9ch\xafh\xa4SU\x8alxɋw\"\x03\x9b\x1b\xef\x91d\xc0\xfebp\x84/\x0f\xc5\x11z\x9fZ8\x8a\xf6\xa2\u007f\x8a8*#4<\xb2\x89#\xa3&\xb6qd\xc0\xfeBp\x14\x1d\x82P\x90$\"/n\xa4\x98\xb3\xf0ú%\xfa\x1d\xb8:9'\\\xf4\x97\n\xba\xb2\xc8Q\x8fD\xe0\xe1\x1a\xb9\x9b\f\x95\x8dKOT[\x99\xe7nq\x05\x03\xfd\xff\x1a*\x04r\xed\xb3\r\xbd\xc2}5|\xb6\xcd|\xa1B\xa4\x1e\xd0\a\x95n\"\xa1\x19v$\x8a\xa3\v\xb2I\x1b\x9b\x00\a\xdc\xe7\"\xb6\xb1\x9d\x83\xe3s\xfa\xb0%\v\xfe\x12\xe1\x19 \xbe\xb9\x9fH\xa1Q;\xde^\xc0\xbb\xb3\xf7e\f\xec(\xc0\xfeZ\x9c\xd1S|\xf2U\xeacW\xe6\x8bq\xd3\x15\xaeT\xf6\x9b\xaa\xa7\x92A8\xf04\xb6\x12TA\xf5\xf2\x8cH\xc8\xf0\xe2\x9egh\xf7֡u\x12\xb7O\x8d\x05{\xce\xe07\x0e\xf5l&x\xdc%v\\5\x86\x05\xbcF{K\xccm_\xe2`\xff\xc1\x0e\xf7F\xed\xae\bw\xa6\xecqoXwE0ȏ\xe3\xdeX䊾\x92滚\xd1\xec\xb6\b\xef\xf0C6i\xf9\x9b7\xb7\x17m\x90q\x9c\x1d\xf3z\xa5U\x8f\rLBӜ)\xc5\x04'\x0f0[\nq\x1f\x05\xf7ԧ\xce/\x98^\x96\xb3i\"\xf2F\x16\xfdD\xb1\x85:w'{b\xb0\x13\xd7\xe4\x84\xf1\xcc\xdfz\xb0\x1eB\xae\x95\x8f\x18\x98\xc5\xc4iY\x15V\x91\x00]\xa7B\x97ຍ\xf6\xeb\xd8\"UxcძTۤx\x1dYP\xfc\x009F\xe3\xc5U\x97iT{\xb2\x84Y\xefK\x9c\xb85{iC?\x1f\xbe\x8d\x805\xd5\x12P\xc3\xdb\b\xfc\xb5\x86ER\xb0\xc5!\"\xed>6o5\xf4\xae\x15\x12\x1bю\xb4%O\xb0v\x9b\x9b\xe2I\xd3\xe9\x10Uǃ\xf8\xa3\x82ަ\xacX\xd2\t:\bP\xde\x18\x81\x16\x05\xd1\x1b;K\xc1\x85\xb4\xc7ۨ\xf4\x82G\xf4\xfc\xb6\x03\xfdW6\xdf\fi\xd6)\x1a\x8d\xedz\x15\x9f\xeei\x86K\x87\xc3\xf46\xac\rd\xd4\x16\xeb؉/S\xff\xc0\xf4\x12\xdb7-\xa1\xf5\x81x\xccJP\x98\xb0\xc4\tH)\xa4\xbb7\xe2\x13\rb\xeb*[\xfd\a/\xb7\x18\xa6@ͿNԐ\fZ\xd2j\x1fk>\xa0\fǁ\xf9\x1c\x124\xd9\x1b;\x17\x05܆hN\xeb~c\xeej\xb8aB曑\xc7+g\x8f\x06\x03M60\x10\v\xbe/V7\xc8\xe7SB\xae\xe2\fQ\u007f\xb1\xfb\xccp\x9a&tw\xb3(\x96\x14x\xab35n\xa2\v\xe7\xc5I\x06\xc0\xac^3\xa3x\xc9\x10\x93oA\x9a9\x17G\x11Ø{မ#\xe8\x98P\xacOl;\u007fc+\x1f#\xce9\xb6\x99\xc3\xe1\xfdc\xd11\x84=\xb9\x1c\x84\x85\x87q\x89͙:j>\aّ\xd3\x11\x9f\xddD\x9e:É<]\xb4\x99\x1c!\xe2L>J\x94'\xeeⷭ\xe8<\xb0\xcd\xefm\x03JãiT\x8f\xa0\xb5;qj\xab\xdaWU\xb1\xb3\xb5\xaf\xc6\xcf\xfe;4g\xbe\xdd~\x9e\v[l\xa0Y\xea\xde\xf55\rSSJ\xaeY\xe6\x83Wy\x91\x19\xe3\xb15\xe3\xe0lH\x84\xd5\xe87|V!\xa3no\xec\n\xfd\x87\x9d\x97\xffB1T\xb54\xf6\xf5\xbco\xaaO\xd9\xe8G\xa0\x06\xec\xda\xcfc\xc96-|\xbc\x8d\xa4l>\a\u007f\xc39P\xec\x15T\xd2\xdc\x18\x0e\x8a\xb8\xd4\xdf\x19,\x98\xbdfZ\xa9V\x81\x11\x8a\xaaHؙU\xf7\x98&9[,\xad\x97\x86P,E\x19^nR\v\x92\t\x9a\x12\xe4\xe2B\x92\a*sc\xb1\xd0d\x89\xf5\x1b)'i\x19|\xf0\xb1\x93\xdcz\xa24\xd5@D\x01\xb6\xa4\x84\xdd\x1b\x83o[]+\x8cL\xc7\xe6\xd3c\xf3\xe9\xdecl>=6\x9f\x1e\x9bO\x87\x8e\xb1\xf9\xf4\xd8|\xba\xf7\x18\x9bO\x8fͧ\xc7\xe6\xd3v\x8cͧ#\xc6\xd8|z\xd7\x18\x9bO\xf7\x1ac\xf3\xe9\xed16\x9f\xee\x1cc\xf3\xe9\x8e16\x9f\xee;\xc6\xe6\xd3\xd5\xf8\xe54=\x1b\x9bO\u007f\xaaM\xcf\xc6\xe6\xd3}\xc6\xe7\xd1\x1anl>=6\x9f\xf6x\x19\x9bO\a\x8d\xb1\xf9\xf4\xc6\x18\x9bO\u007f\xaeD56\x9f\x1e\x9bO\x8fͧ\xbb\xbf\xfbk\xb7\xc3\xc6\xe6ӟ\xaa\x1d\xf6yX\x18c\xf3\xe9\xb1\xf9\xf4\xd8|zl>=6\x9f\x1e\x9bO\x8fͧ\xc7\xe6\xd3c\xf3\xe9_\x91W1\xf2\xa6HʂZ\xb6\xf5\xe8\x16\x10S\xfb\xc4\xd7\xee4\x8c\xac\x9c\xcfA\xa2\xf0\xc5\xd9y\xe5(\xee\x12\x98\xef\fU\x89n\x97\x11\x8b\x8d\x02%\xd0\xd4ּ\b\xf3\vvN\xcb\x17!\xc5\xf6e\xf6^j`x\x80\\\xbe\xfd\xbav\xbaƴ:\x88\xbb\x1d\x88\xeby˓\xf8\xbbB5!tTg\ríM\xc0O2\xa1\xdc=YDv\xb2\xa4\x9cC\xe6\x94n\x16\x86\xd9%Ud\x06\xc0\x89(\x80[\xb5\x85\x12\xc5\xf8\"\x03B\xb5\xa6\xc9rjV\x10\xe6=sD\xe0\xba\xd6\xd53UZ\x02\xcd-1H\xc8C\xfb\f\x9a)\x12\x9aH\xa1\x14\xc9\xcbL\xb3\xa2\x9a$Q\x80\xa52\x02\x93\x96\xae\xe6\xf5\x06c\x92x}\x01\xf5\xacZE\xf0\x1cm\x19\xb4ƙ\xd7T\xea3l\a\x9b\x17zm\xefR\x85\t>\xec\xda)\x95&Iƀk\xb7j[\x9f\x11\xe7yFBs\xe3\xf1\xfa\xae\xdd\x05\xe5P\xcbS\xf4\x8a\x14Zٛ>q\x13uSL\x99r\xde7uF\xa8\xf6\x822\x98\xe8=-!\xd9{\x05\xce\xce\xda\xfd\x149ͺ\xa4\xbf\xaa\xaf\x9a\xd5\xccp\x9e\xd10\xc5\xd03\xa5\xb3V-\x87\xda>\xc4$wd\xabA`\xb1\xec\x90\xc5\x02\x1e\x1c\x0e+\xc3? \x01\xb6B\u007f\x90\xe1\x8cA\x107\xb9\xe8\x933ц\xee\xfa\x06\x94\xa2\v\xb8\tL\xb1\xd9\xe5 \xc6,\x9b\x9a\xb8\x02\r.\xacF\xa6EC\x87\xab/\xa0\xb4-\xd0 \xb0\xb9]ces>H\xa65 \x11c\xe7*\xcc<\f\xcc\x03ߚ\\\xf3z\xcc\x1b\xffA\xfb\xa1P\xaa5\xfa\x14O\xed\xa5\x8e\x19\x90\x99d0's\xc6i\xe6\xeea\x84]8\xc2~\x16T\x19ҤJ\x81D\x9f\x8bs;y܄\x11\xec\xf7\x0e\x91Z\x96<\xa1\x8d.\x97X\xfd\x8e\xcd\xc9\x02\xefz\x04\x1a\x13K\xcaɿ~\xf5\xef\u007f$\xb3\xb5т\xd18\xd6BӬ\xda\xc0\f\xf8\"\xb0\xb6\xbf\x13O\xed:d\x15%d,g\xa1n!c\f\xfc\xee~\xd6\x0e4\x9e\xa7\xb0:o\xd0\xe7$\x13\x8b0\x9c\xbe\xf2\xf7+\xab;\x93!\x8a|\x94k\xbf\x83\r\x88\x8c%\xebhF\xe0\x9b琥x\xb0\xae\xbc\x81'\xb6\xbe\xe2X\x88\xa2\xcclJ\xc6\u05fe\xb2d\x10\xc8R\xc1v5\xacN>\x18J\r~j\x9b\x1d\xc2\xed\x95)\xb7\x940\xa5\xc5\x15\x9es\xa1\xf1\xaag\x0e\xfa\x89\xbf\xa6Y6\xa3\xc9\xfd\x9d\xf8N,\xd4[~)e`\x9b}\xa4~\x8f\x8f\x8c\x1a-fY\xf2{ly[\xd7\x1a\x16a\xd2V\x94\xba(\xb5\xbf\xe4\xddt\xef\xfa\xcd\f\xae\aY)h\xde3\\\xcf\x0e\x1e\u0379E\xf7l\x18;p\xc5w,w\xc9Ģ\x9a\xb7\xf2\xcc \xf4F\xd0\xef\xbe\xfa\xd7\u007f\xb3,\x8b\bI\xfe\xed+\xbc2\xaaά\x10C\xdd\xc0(\xb29Ͳ\xd0`V\x93\xc1\x18\xa2\x9fv0\x89'\xe7\x11:\x9e\x1d<\x89\xc9}w\xf7w\xb4\xb7\x99V\x90\xcd\xcfl\xed\x11\xefA\f\x02z\x82J܉\x93\xb2X\xe4\xe6#\x18\xb4+\x91\x959\xbc\x86\x15K\xc2\"\xfc-T\xb7\xa0\xf8HPƔ&\"\xac\n\xc4,\x13\xc9=I\x1d\xa0\xc6\u074c\xcd>\xd6!\x98\x89\xb8\x85\xb2su\xf5\xfd\x13\x12ڌ(\xa7EQ\xd5r\x90\xf4\xa1\xb5X\xe4%\xc1\x17Phl\xa0:>\xab\xc3N7Ta\xf7\xef6\xb0Z\x03\xf2\x04S\x84J?;\xdc\xcd뭆T\xbe\x83^T\xae\x81\xdb\x13\xab\xa7\x99\x9dC\xce\x1c\x1e^\x1f\x90\xf4\x10w\xa7\xa7\x85c^\xe5\n\xe4T;\x9b&2\u007f\x06\xa9\xb6\x00\xa9\x982\n\xcc{<\x13\xaf2\xca\xf2\xf8\x1b\xfe1\r\t\x06\xb4\x80\x8d\xc9K\x984\xe84\xf0\xc5`D\x0f\xaa{\x14v\xb7Ų4l\xe9\x1b\xcf\xf5oD\xea\x00!\xab\xb6m\x98\x8d)\x1bL\x0e\xbb\n=\fR8\x86\xb2\xfd\xf75\x8e\x9a\\߮3\xfc8\xe3\x01\xb20\x1d\xb3\xff\x18\xec\x1b'\u007f\x04\xee\x8d|\xdb-chݹ\xa6\xc3\xc6\x11T\xc3\xf4r>\x92\xa9͍\x8d\x00o(\xc8M\x8f\x9c\xbc<\xf9\xa0<ܢ[\x8a\x82.\xd0\x1a\x19\x88\xf5Mp\xc3\n\xcd\x1a3\x19!V=c\x10.\xa4Um\xf3(\xa0\xf6B}-\x87\xbd\xf9\x84\x95\xc7\" >\xd05\xa1R\x94<\xb5\xb1\x87:(\xf5f\x03\x1dׂ\xc7L\xd9E\xbf]\xa5\xa9\xaa\xa6-\xa6\t0N^L_|\xf5\xb9\t~\\Ɇ\xe0\x8f,\xfc\xdc\xe0[\x1f\x14\v\xbee\xfb@L\xbcq.ֺ\xc3zT\xd9I\x1b\x03B \x0f\x92iG\xcd\x0fL\x019\r\xf5\x9a\xfb!d\xb3\x96\xe5\xf3\xb6K/\xaaw\xfb\xb0\xa2\xa7\xaa\x9c=\x81d\xb0\f=\x02=Ȅ\xba|\xf1*\x1ef\x87Xi\"\xfdYL\xa7\x8fS;\x9b\x13[\xf5\xea\xf9\a=$n\xcb.\x1f\x8b\x88\xceq\xadm\xbb|,(z\xfd\x8bz\xffb\xceI-\xc2w\xef_\x04\xdc\xddj\xc1_`IWQ\xf2O\xb1\x9ceTf\x98Zvk1If\xa5&\xc0WL\n\x1eu\xfb\x82\x90\x15\x95\f\xab\x8dK\xc0Z\x90\t(\xf2\xe5\xe9\xfb\x8bw\x98\xa1\x1dS\xb8˖\xe9t\xfbS*[^|(F\x1b\x8b\xdc<\x045IG\xc0\xb5\x87\xc0\xe3\xd3P&j\x00\x1e\xbf4\"U\x89\x90\xbc\xd4%Ͱ`[\x92\x95\x8a\xad>\xa4,\x8a\xb5\x1c+]\xfb\x17d8\xba\x92\x81\xafY\x10\xbf\xd9(\x8fX3\xf2\xad\n\x84\xc1\t\x1b\xa8\f\xd6\x15n;\xd3j\x02\xe9\xd87\xa8j&\t;\x87\xba\xab\x9ej\xaf\x10\xba\x9eo\xa1\xa9K\x1b\xd9\x069]|\x04\xd7z(M\aQe0=\x86Q\xa2\xcb\xfb\xec7\xf5\xb6Zl\xdft=\u05ec\xd71\xa7\x8f\x98PI\xf1\xb8\xf6\\\xa1\x98\xe3,\xc8{\xc8@\n/\x96\x1e(\xd3\xd5}Sƙ\x0e\xee,\x81\x86\x93\xad\xa7\u070f\x00\x82\xb6\xbe\xf7\xbe\xf4|\xf0\xf0\xb6\x1d\"\xb3\xbddup\x16\xfb\xbe\xbf\xe7eƓ\xacL\xe1UV*\r\xf2\x1d(Q\xca\xce\xe8\xc7Ft\xb9\xf3\xadƥ\xd2\a\x17pJ\xec#\x13\x95\x88\xa2\x93=\xc8\xfa\xe5J\x9fq\x93J}\xc1\t\xbc\x9f\\ݤ\xb1\x95\xbd\x94\x16\x12vT\xd6\xe6e\x96m\\j\xec\xec\x9b`\x9e3\xdaɎ\xbb]\xfb\xec\a?EcH\xaa\x82\xf6FY\xe3\x05\x9b\x80\xaf2\x96\xa0Þ\xfb?\xd8\xff2\xb3v\x1f\xe9X\xa1\xddK\x9b\x84\x8ayY\x18\x9d=\xc3\xe4\n^\u007f\xc1VP\xb0\x1f\xde^\xfeN\xa7\xe0ރ\xd4\vi]t\xe8'\x12Hd\xf5\xf3\x1b\b\xf3\x94\xd3\a_\xdbd\xd3\xc4XM\x83\xee\xb9\x19M\xee\xcb\xe2\xd3B\x1fv\xa0\xbe\x85\fu\x83\x03\xa8\xfb\xae\xf9\xacE[\x0e\x9a\xae^L\xdb\u007f1\xb65\xcb4f!w\xaaf\x0f6\x13\xd2`\xcd^8Kي\xa5%\xcdZ\x14\xd8\xc0Y\x8dZ\xbc\x90ʲ\xae\x04),\x89\xeb\xdeoḺ0\x18|V\xf7{\x81\xd1\xf1c\xd4o\x97\n\xdb͂\xdb\xeeōW,\x16]\x1c\u05f5\x03W\x1e\x8f\x8e\xb5\x1b\xfbag\x9a\xed\x9d+H\xe8\x9fÕ_\\\xbfޥ\xde\xecuٷ\xa6z\xb1g:\xee\xccT\x1b\xbe\xaf\v\x83S\xc4ܝ/uF(\xb9\x87\xf5\x99M~\xe5\xae\f\xbd\x03b\xbb\x06;\xb5\xe1\x1ev\xab*\xe6e\vo\x17b\xfa8\xf0\xefa\xaf鉶\x8e{XWawċ\xf9\xc1\a@kT\xb86\xee\xfbe\xff\xde(g/}\xc3c\xad\xf7\xf4+4K0\xc4gIŬ\xe1D\xb9V͂\xab%+\x0e%\xc7PL\xd9\x16s\x8f\xfd\xaay\xaf\x05o\xe9\uf29f\x91k\xa1\xcd\xff\\>2u\xe0B\x8e\xd9\xcb\xd7\x02Ե\xd0\xf8\xf4`\xe4ة\xf5F\x8d}\x1cI\x9a[\x1e\x89\x97\x94\xf0\x1b\xd52\xaf\x0e\xdf\u007f\xafP\xcc\x14\xb9\xe2\x86Q9\x1cT\x97\x15\x95\x03\u07fcc\x88\\m\xbf&j\xbf݂o\xd1j\xbe\xd1\xc4\\\xf3S\xfbQޚ\x86\x9d\x82\xf5hۿ`\x82v\x91\xd1\x04R\xd7g\xc2l\xbc\x96TÂ\xedo?\x90\x83\\`\xa2A\xb2ܷ\xaa\x1e\xa1Þ\x8a\xf71T\xe4ݬfR\xa1\xfd)Th'CP|\xee\xc0\x86\xef$F\xb3\x9b\x83\x1c\xed ƶe\x91\xfd\xb4\x13\xe6\xb40\x94\xff?\x86=#\x11\xfd/)(\x93jJ.\xdc\r\x95\x1d\xdfm\xbe\xe1t\x9d&p\x03\x97)bvaE3\xb0\x85\x8a)'\xb0\xb7\xfc\x8a\x98oI\xcb3\xf2\xb0\x14\n%C\x1dDzv\x0f\xebgg\xad\x13\xb2\x03\xa2y\xf8\x8a?;\xab\xe2e\xadCY\xc9)\fa<ÿ=\x9bn\t\xd8\x1d\xb0\x0f\x88ݽT\xb2珕\xd6\xfdƦ6m\xef|_\xfa\xd8K\x1b[\x15\x18\x9b\xdfl\x11GS9n\x99\x15]\x9f\xa4r\x01\xba\xcb\x04q\x1a3\xa62L\xc9\x05_o\xc1ŋq\x9d*\xb73\xe2*:+Z티\xa5%fH4@\xb9\xc4%\xd5m\b\x9b\a\xb7wmϦ\b\xd9\xd2w\x0fY\x1co7\x1e\xb7\xa9\xa8V\xe3ۯ?w\xa9\xceL/#\xf5g\u007f\x83\xab\x03ju\x89^/a]\xe1\xf3\xbf\x04\xe3ub\xe0\xdbw\xd5\xf9\x9an\x98\x02\x9d\rS\x1f \xcb\bU\xdb\xcbw\x8d\x86\x121\x01#\xb4\xccNzzp\xa5\xb5\xcf\xf0\fv\x19\xa8U[\x9d\xbc\xd9\x1f\xaa\xbf\x11\xb5_õ\xca8\xfe\xf6\xcf\x12\xe4\x1a\v\x0e\xd4*Oe\xd0u\x9fq\xcb)\xb0\x05\xa8\xe7]\x8e\x01\x1a~\xb3\xa5\xf9\xd7\x1c\x83\\p+\x83;\xc1n\xcc\x11\xe1\x80jZ;\x86?\x1bCfǣ\x9dP\xb9\xa8\xde\ue987\xbd\xa2\xa6\x9f\xe5\xf3ԶO\xb8\xf5sP\xefx\x12\v(\xde\x06\xda\x03\xd2\xc8\xc0\xc3VP\xdfD\xa6\x03\x96\xd0\xd3\xd9B\x87\xac\xa1\xdej`\x1f\x8b(\xd2&:\xb8\x80\xa7\xb0\x8a\xc2\xec\xa2\xdeh:l\x1b=\x91u\xf4\x84\xf6\xd1SXHq6\xd2\x01\x90\x95\x05\xd5\xd7J\xea\x99b\xd9;D\xd1'\nt8n\xb5\xcf^\xeaa1\xf5\n~\x1c\x9a\xe9A\xbb)\xccr\xea\x85\xc3'\xb2\x9e\x9e\xc8~z\n\v\xeaim\xa8\x83V\xd4A\xca\xd9\xfb\xe7h\x1f9\n\a\xb9\x82k\x91\u008d\x90]\xf9\xdc\xed\xfc\xac\xcd\xe7;\"X\r#Hd)ޫ\xc5G;\x16\x85\xba\xbc\xd3\xe3\xe3\x16\xd5\x1dlr߿y\u007fh=\xef\xaa\a\xf7/\x84b/=k\x9fu\xacüo\xef\xd6sZ\xa8\xa5\xd0\xe4\xd4\x17\xb1J2Q\xa6\xce\b\x91\x1d\xf9]\xc3Wy\x8b\x975\xfb-\xd4>\xdbZ+K\x96\x8dx\xceC\x95&\xe5\xa0w\x91\"\x16\xe1@@x\xd0PHbŵZ\xf5\xfe0a\nL\xe8\xd9\x1f!\xdb\xc2\xc4\xe5\xe6;\x1b\xcd\xc0j\\\xf8\xdb\xfc;\x0e\xac\xad\xa0 tE$5^\"\x02\x14\a\x99\xf4\x01D\x91\x83\x92\xa5G8q\vY\xdb!\xc5!\xc8\xea@T#\xb0ȴW\xabQ\b4Ì\x9f >\xf7\xf0c\x95,!-3\xe8n\xfe\xbf\xd5.\xc2?\xea펒\xb3\u007f\x96ЬM[e\x8a\xb8\xa7\xbb\xcedͫ\xaa\x10w#\xb3Ɉ\xb4\xbf \x9f\xf5_rHw\x90w\\Io\x82\xb4\xb2[(\x8d\xf5B\xb8n\x14?\xf7\xe1\xdfĵ\xc9t\x8fw\x96\xbb\xf1k\xd8\xe5\x96\xeaرn\xb5m⾺\x95\x99\xbecgT\a\x9b\xdc\xc3\"\x13Z\xe8R:2OJ\x89}\xb9\xebV\xa2\xd4c\xae\x8bM\xeefZ.?\x87\t~\xc7rP\x9a\xe6\xc5\x01\ny\xb5\xfd\x86\xd9\x00!SUU\x1cm\x86\xea\xeb\xe6\xd7]\x8e+Z\xb7\\O\xa7\r\xd8\x16\f\xea\xfd\x064\xa4\x04V\xc0\x89+\xb6\x01\x954\xe8:\x88wh\x18\xcb\x15\xe6\xe4y8x\xefv.$\xc1\xee\xf6\xd5Է)\u0097pK\xa9\x86IgE\x9f^\x12\xb2\xf3\xa0\xe3u\xf9C\x92\x11k\x108E7\xc1\xfbZf{\xb3̾\xed+\x00\xb8\x92;\x0f \x81,\x80\x1b\x14wj\x02\xce\\\xb2-\x97\rb\xdd\t\xae\x12)\xeel\x97꒺\x0fXIYyw\xbb<\x83H\xc9\xf8Hg\xb5\x93}\x85\xec\\\xe5\x85w@U\xd7\xfd\xa1\x16\"\xben>\xeb\xacb\x8b\x03\\zBm\xbf\xfa%\x10\xe0\x9aIا!\b\xfcr\xc0\x19'\xa4XRu\x88]ޘg\xaa\xd6؍CYq\xcaw;\xe6\x04\xbc̷\x81O\xc85]\x89\xbc\xaaX\xeae\x1f\xd9\xfc~\xe3\xf1\x8d\x84F#\xa5k\x88N\x9ev \xe7\x94ͭi\x91\x98Yo_\xa2\xf9\xc0\x89\x89\x0fTr\xc6\x17\x87\x16\xff\xbd{\xacC5q\x10:\x94\x93\x8eET\xeaJ\x90r\xe2'\xb9\xe3\xceM\xa5\xb0\fPO:\xcf\xd0֏H\xc8i\x03\xc9\xeeK\xee\x97Z\xad\xb7\xe5&]°\xc5\xed=\xe3\xe9K\u007f1\xaf\xc8JI3\xf7\xcfDp\xcb\x16\xd4K\xf2Ï_\xf8\x05\xbd\a\xa9\xaa\x1f\xff_\x00\x00\x00\xff\xff\xc8\aW} \xfd\x01\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec|\xbd}\xf8\u05fbN5\xf4䠚%H\v\x02\x1eX\xa8\xc1T\xcb\x0f\xdcN80H\\C\xe5\xa8Eap\x15(\x93\xd6 \x01\xb4\x81\x02\x8dԩL\x02E\xb9\xb3\xdd\xe92Ka\x83D\xdcuݡ0\xba@\xe3dX6\xbe\xb4\xd4D\xab\xb6\x87\xf1;\x9a\x94o\xe5\xa5\b-\vN\xb5\x180\xad\xe8\xe0e[\xda\x06\u007f&p\a0P#\xa1@o~\xc3ĭ\xe1\x0e\r\x81\tX'Z\xed\xd1\x10\x05\x12\xfd\xa8\xe4\xffְ-I\xaccArX\xad\xe5\xa6\xf0\xe2S\"\x83\xbd\xc8J\xbc\x00\xa1R\xc8\xc5\x01\f\xd2(P\xaa\x16\xf5\x99\xee-\tkX@\x04\x93j\x8b\xd5j\xdc\x1a\x9d3LTi\xa1\xa5r\xfc#\xc9$\xaa>\xf9m\xb9ɥ#\xbe\xff^\xa2uī5\\\xb3\xcd 9,\vZ=\xe9\x1an\x15\\\x8b\x1c\xb3ka\xf1\xd5\x19@\x94\xb6+\"l\x1c\v\xda\xe6\xae\xdf\xd8S\xad\xf5!\x98\xa6\x11~\x855~W`\xd2Y2\xd4One\xc2\v\x835_\xad\x02z\xdaϗ\xe1U\v\x95\xea\xa1\xe6\xfd\xfaIm\x13k\x13\x8e`B\xa5b\xd6G_F\xa8ɟ0/h\xb9Πx_5#\x14\x89Fi\xed\x82\x04c\x19ԛ\xae\xb4\x1a\x1c)\x15\x1en\x87D\xaf\xbdL+\xadqD\xcdi\x8azĶ\xa2\xcc\xdc\x03\xd9q\xb4\xf7\xfa\x1bZ'\x93\xa1\x96\xbdI|\x1c\xec\x18\xf8\x8d\x96(\xecvhhq\xf2\a\xd6w\x83p\x81\u05ccŔU\x9ex\"\x93\xb9\xf1\x14 ݙeP\xe8\x14\xf6~$\xd8\x1c\x02\xd2Ǽi\xf8\xb3\xd1:C1D5\xfc\x9ede\x8ai\xed\xe6\fҥ7ۛ\xa3N\xec\x10\n\xa9H\xca\xc8\xfd\"TU\xfdud\x9el\xaf\x84A E!\x95\x87\tһ%\x9b\x11\x81\xa3\"\x1d\xe6#xNJ\xa4/\xe4x\x8aM\x86W\xe0L9$\xeb\x01\x860F\x1c&h\x16\x9c\xe6%$\xab\xfbT\xea<\x93\t\x12\xb1j\xa5\xcdTcҌ\xcc\xef\x1f\x90`;\xad\x9fb\x88\xf4\x1fԮ1N\x90pl\x02\x1b܉\xbd\xd4\xc6\xf6=\x1c\xfc\x8eI\xe9pl\x1d\t\a\xa9\xdcn\xd1\x10,v\xa8k\xff{\x8aX\xd3*\x82\x8a\x99f\xfcѼ\x1a\xa6\x13\xf3\x98\x1acSaU<\n\x15\x18q\xd2\xd8e\x01R\xa5r/\xd3Rd \x95uB%~~\xa2\xc6ox~0'\x10G\xf8{\x05\x1cfA\\\xeaX6\xad\x90\xdc\xd1\\\x9ba\xe1\b\xe5\x18\xcc8\x196\x824\xa0\x1e3GM1\x14\xc5U\xa8\xa4lR\x1b\xbds\xd1p\xca;\x85\x99\xd8`\x06\x163L\x9c6\xe3\xe4\x89\x11\x02_b\xf5\xe7\be\a4ic3HPg\x95hS\x9c\x86\xe7\x9dLv\xde\u007f#)cX\x90j\xb4\xac1DQd\x87\xa9IC\x8cdT\x83\xcd)\x8d\xa6D\xa8\x8f>\xdc1EҔH\x1dܔ\x19mܥz-6oD\uf829~H\xd8o\x8f\xba\xbf\xbc\xb0\x13\xb9%\xc5w\xb7[\xc0\xbcp\x87\v\x90.\xd4\xc6@%\a\xab\xc1\xe3oƸ\xd3V\xcbm\xbf\xf7\x8b\xaf\x96\x17\xe1Z\x8d\xc6߄il\xac\xee*[\xb5\x88a\x9f\xda=/@nk\x86\xa5\x17\xb0\x95\x99C\xf6\xa5\xe6\x10m9:\xb3\x9c{I\x02\xc5\xda^*\xb9p\xc9\xee\xa6\x0ei#z\xf4h\xd5\a\xe0\xfd\xf2\x10\xc30\x0f\"@B\xedT\xf0.\x884\x98\xfbݕ{^\x1fM\r{\x80\x1f>\u007f\xc4t\x8ed\x10/\xa9G\x93\xfa\xd0\xf3t\xda(\xf0\x04\xa3@\xb6&\xc5nZ\x1d\xe3\xf9=\xb4\v\x10\xf0\x84\a\xefY\r\x06\x97C\x85X+j\x90\x06yC\x8f\xd5\xc8\x13\x1e\x18T\xb5C\x17\x05o\x89\xa8\xf8\xf2\x84\x87ئ=\xa2\x12~\xd5\x1e\x85\xa7.U\xf0,b\x96RSj\xa2Vk\a\x9c\x8e\x9b,,SJ\xa1\x04\x8a\x9f8\xed\x9aa\x9dm\xe9'<\xbc\xb3\x9e}\xb4jv\xb2X@\x01R\xd8`\x91WX؏}\x10\x99L\xeb\xc1x\x9d,\x80x\xab.\xe0\xb3v\xf4\xe7滴\x84\xa2J\xe1\xa3F\xfbY;\xaeyU\x12\xfbI\x9cH`ߙ\x97\xa5\xf2f\x81\xe8\xb2h\xfc\x06\a6\xa1$\xa25ۤ\x85[E\xf1\x99\xa7\xcf\x126\xed0 \xe7\xd1\xcaK\xcb;\xbaJ\xab\x15\x9b\xe90\xda\x02\xa0m\xbc*Vi\xd3\xe1\xd4\xc5B\x88\x83(V\xe8ݓ\xb5\xf2_\x8e\xf6§\x8a\xc1\"\x13\t\xa6\x90\x96\xbc\xdf\xce\x1b\xef\xc2\xe1\xa3L G\xf3\x88P\x90݈\x17\xaa\x05\x9aܗ\x13\xa40\u07b5\b\xa52\vi\x1cb+Z\xf5\x91-\x03\x9b\xa3\x9a\x8f\xec\xb2O7\x8f\x9b%\x9bw\xf6\x87\xa2\xa8\xdf>\xd2]fY\x16\xf2\xeb\xd8\a\xf1Hz\xf7#\x17\xbc\xd9\xfb\a\x99W\x16\xef?㬡\x90Ʈ\xe1\x03\x1fhg\xd8\xee\x1fv\t[CE\x81$L\xa4\x05\x92\x93\xbd\xc8\xc8} \xe5\xad\x003\xefL\xe8\xed\x91\a\x15\xa7b\x9ew\xdaz\x9b\xbf\x95\x98\xf1\xe9\xd6\xf9\x13\x1e\xce/\x8e\xb4\xd7\xf9\xad:\x8f\x83I:\xffHi\xd5^\x8bV\xd9\x01\xce\xf9\xdb9;fK\x96\xc8\t\xce\xdb\x02\xa9\x8en\xca\xc7\xcfKB\x01\x8a\xb5\x83\xd7B\x9d\xebCZr\xe1\xe7f\x11-Ӆ\xb6n\x11Z_\xb5u~\x03\xb0\xe3n\x0f\xec\x10\xc6D\u007fծ!\x88\xadC\x03\xd6i\x13\x0eDI\xed\xf66ȉ\xf3v\x9e\xf7\xc4\xeaz7\xd2\x03\xa6 \xf3\xbc\xd1\x10^\xa7\x9f\xfb\x93R\xfa\u007f\x1ef\xc2\xce\x12\xc3.\x8cN\xd0\xdayQ\x8a\xb4\x1c3\x1b\xb6\xf5f\xad\xf0\xc1\xdb6J5\xc7l%\x87\xb2\xcc\x15'Ҟ\x10\xd8\xdc|o\xed;\x93\x1a\xa2\xdf1\xa2|\n\x8e\xc0\x89Ny.\xfa\x87\xf3\xd1\xe8^\xfb\xdea\x01V\xc0|\xc0d\x1eKV*\xcb\xfc\xe6J$\xffj\x8eG.\xd5-\x0f\x04\xef_\xcdY\x81\xa0\xca\xf1\xd4P\xe6:\xf4o\x18RW\xc4Ư\x10\x8e\x9a5\x9f\xd5\x18\xecp\xf6\xf8$#\x9eS@δҮ\xbdYS\x8d\xf4\xce\xc2V\x1a\xeb\x1a\x84\x17@\x95\x96\x8f\x93_7\xc6T7Ɯ\x1cb~\xf1\xbd[ۊ;\xfd\\%F,\t\xac\x03\xf1wb\x8f \xb7 \x1d\xa0Jt\xa9xË\xd4\x05\r\xb3\x00\xa2g\xa27&\x916\xb3\xd5Y\x95y\x1f\xa8\xc5\xe7\xa5-\xcdF\xab\xf3\x87\xe6\xad\xca\x0f\xe4\xa0-\xbb 0\x9bo\x16\x834\xc4d\x99\r\xe7\x8f\xcd@]\x92[\x16\x1b\x83G\xe4\x91\xc5g\x8fő\a\xf8\xc6nl\xceX\xb4\xd7\x16\x9b\x1f\xf6:Ya\x91\xb9`\xad\f\xafY\x90'f\x80E\x13,.\xdb+:ǫ\x95\xb95O\xad\x89̮\xe1|\xadY\x90C\xf9\\1YZQ\xb8F\xe7f\xd5\x19W\xf3;\x89?\x94\x91\xf5\xf2\xb9\xdf/\xe9\xe7O\xe7WEeUE\xc5\x02\xf38G\xe5M-͖\x8a\xa2\xea\xd2̨:\xebib\xe0\xa8|\xa8\xe3\\\xa7\xa9\xa9\xccfA\x8dg8M\x81\x1d\xca}\x8a\xc8k\x9a\x00\xd9\xcexZ\xec\x06\xccJ\xd3L\x83\xe1[\xf5\xa1\xcc\xdb\xda\xec\xffC\x02\u007ft\xd2\xdat\\\xe0\x98\xa8\xe4K\xaf\v\xf1>x}Cn\xf5x\x8c\xe7\x9d\xed\x13\xdc\xea\x11\x90\xb7[\xc8\xcb\xcc\xc9\"k]\xafw;<\xc0\xb3\xcc2R\xe7\xbfi\xbez\xb990\xb4/\xdfj\x01\x1e\x03\xd9\r\x10\x84\x85g\xcc2\xfa{D\x85\xc4?\"\x91\xe8\x15\x92\xcd\x19\xdf\x06\xaf.\xc8W/P\\\xf8\\?\xbe\x97\xca\xf6,'H\xe1^\xfd\t\xe1״\xb3\xeb}t\xae\xfb\xbdDs\x00\xbdGS{5\xa3b\xd6\xdcW\xaa\x96\xa6-\xb3F\x95T:\xc9?e\xd2U-㫡^\xd0\xf0Ay3\xdbǕa\x91\x0ei\x82\xa3)\xd5I\xb1\xd0\x18\b\xa5k\b#\xfdc|\xe9%\x17x^#Tz\x89`)ʭx\x8d\x80\xe9\xb5B\xa6\xa5AӒ\xa3˨\v8\xaf\x11:-\t\x9e\x16y\x80\xf1\x17l^\xebb\xcd+\x04Q'\x87Q\x8bH\x17{qfq0\x151\xbf\x99\x8b2G\x1eW\x04\xc8\xd1\v2\xc3\x01U\x04ģ\x8b1\xb3!U\xcc:\xe8\a]?|\xcd%\xfa\x18\u007f\xd1YR\xec\x11|\xdc1\xcf\xfc\xf5\x95\xc8k+\x91\x87@1\xd8G^OY~-%\x92\xce'\x06[\x93CG^?Y\x14n\x9d\x18pMB\x9c\xban2\x1drMo\xa7\xf5\xaf\x99\x9c\xe0NDH\xd8l\x93\x1f>\x11\xd0&E3{\xb8\xb2D4g\x85\xb2\x17\x13u\xc7\xef\xbd:\x10\xdeĢV탛1\xee\xe8\xfa\x16|\x02\xbfJ\x95zސ\x10\xb6\xfc\v~h\x8f\xef\xc9Ԏϸ\x185\xdef\xef\xd0\xc8b!H\x8drPć\xdbv\r7\"\xd9\xd5\rG \xf2\xc8;aa\xabM.\x1c\x9cקq\x97\xa1'՜\xaf\x01~\xd1\xf5Ah땛\x11\xb8V\xe6Ev\xa0\xe8\aλ\x80~LtF\xc5\xcf*Q\u061d\x0e\x0f\xa2ED\xc0w\xdd\x1e\x03Ǿ\xe19\xb4$\xd3eZ\x8f0\xc1n\xa1\x0e\xf0\xf5\x81\xbd)~\x04*i\x1e˪|\xa5\x10\t\xf7\xde\xd2\x1a\x019\xf6\x06\xde\"\x92\x8d\x1f\x0e[\xa7\x8dx\xc4O\xda?\x0f\x18C\xb3n\x8f\xce\v\x91\x95\xae\n\xa9\"\xd5ݯQI\xf6s\xeb\x03l2Ȫ\xd5֜\xa5\x13\xb6cJlf\x9d;\x97EL\xee\xfe\xfe\x93\x9f\x90\x939\xae?\x96\xfe\xa0~U\bc\x91(\x1d&\xea;m\xc6\xed\xdcN?C\xa6+:\xfcܟ\x87A\xceX㜀\x93f\xe3_\xe2\v\xe2\x1bH\x17#\xf2\x0f\xc3=[\x81l\x8b\x89SG\xfbz;\nKX\xab\x13ɺ\x88\xb7\x848Q\xec\xf5\x9e\x8a\x9b\xb2(\x13*\xa3\xb4\xf8\xe5Y\xa1\xf9\x16\x16\xaa\xbdU\x9eS3\x8fG\xfe\xd7Q\xc7\xc0\xe0!\xf5A\xfa\xaf\xd7|\xc8\uea4a@\xd6?[\x1d\xf6\xb6\xa4\xad\x9f\xd3<&\xdd\xcc\xfa\x1f_\xfbþ\xebj\xf8\x05\xcbU\xfd\xa8\xe6Y\x04e\xfd\xb3\xc91\xef\x94\xfa\xb7\xa9\x13Q\xb8\xd2T\xe65)\r\xbf\x9bG@\xd0?+w\xdaK\xa5ͫ\xcd3\xbcl\xdeqn\xa2\xfd\xd9W\xa3\a\xf8W\xbfy:\xfa\b\xa8\xb7\xae\xfeU\xe7\x15\xc1?\x8d\x9d\x83\xeb\x80\xdf\x19\x9c\x99\xe9WjS'\xf9V\x84\xe6\x8e\xe1}»1ԇ\xb36W\xf0\x19\x9f\ajo\x14M\xe2\xf8Lͧfb\xca{\x04C\xaf4ONq_\xf7\xe2\xbc\xd8\x01m\xd1Us\xbd潄\x1b\x91e-\x88>\av\x88\xad\xff,\xb7~\x03'\xa19\xfd\xcbQ\x8bQ\xc55\xa9\xb4\xc6\x14\xd6\xe0\x92:\xaa\xb4h\xf6\x98\xb6\x84\xa4\xb2\xe1\xed\x9ars\xf4\\d\xb50\xe1\x8f?Ϛ5*\x92\x04\vW\xa5y\xb5߶??\xe7\x1f\xe1\xe9z\xfe\x99h\xe5\xddn{\x05\xff\xfd?gP\x99\xe3\x87\xf0>=U\xfe_\x00\x00\x00\xff\xff\x11z\x10\b\t`\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xb4V͎\xe44\x10\xbe\xe7)J\xcba/$\xbd+\x0e\xa0\xdc\xd0\xc0a\x05\x8cFӫ\xb9 \x0en\xa7\xd2mƱCU\xb9\x87\x06\xf1\xee\xc8vҝN\xd2̀\x84o\xb1\xeb端~REY\x96\x85\xea\xcd\x13\x12\x1b\xefjP\xbd\xc1\xdf\x05]\xfc\xe2\xea\xf9\x1b\xae\x8c\xdf\x1c?\x16\xcf\xc655\xdc\x05\x16\xdf=\"\xfb@\x1a\xbf\xc3\xd68#ƻ\xa2CQ\x8d\x12U\x17\x00\xca9/*^s\xfc\x04\xd0\xde\tyk\x91\xca=\xba\xea9\xecp\x17\x8cm\x90\x92\xf1\xd1\xf5\xf1C\xf5u\xf5\xa1\x00ЄI\xfd\xb3\xe9\x90Eu}\r.X[\x008\xd5a\r\x8c\x14\x95DI`\xc2\xdf\x02\xb2puD\x8b\xe4+\xe3\v\xeeQG\xc7{\xf2\xa1\xaf\xe1\xf2\x90\xf5\aP9\xa0m2\xb5M\xa6\x1e\xb3\xa9\xf4j\r\xcb\x0f\xb7$~4\x83To\x03)\xbb\x0e(\t\xf0\xc1\x93\xdc_\x9c\x96\xc0L\xf9Ÿ}\xb0\x8aV\x95\v\x00־\xc7\x1a\x92n\xaf46\x05\xc0\xc0T\xb2U\x0e\\\x1c?fs\xfa\x80\x9d\xcaN\x00|\x8f\xeeۇOO_m\xaf\xae\x01\x1adM\xa6\x97\xc4\xf7Jd`\x18\x14\f(@<(\xad\x91\x19t B'\x90Q\x82q\xad\xa7.\xe5\xe8l\x1a@\xed|\x10\x90\x03\xc2S\xa2|\x88\xac:\x8b\xf4\xe4{$1#\x1b\x83ڥ\xfa&\xb73\xac\xefc8Y\n\x9aXv\xc8\xc9\xd3@\t6\x03\x03\xe0[\x90\x83a \xec\t\x19\x9d\xccQ&~ZP\x0e\xfc\xeeW\xd4R\r9\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"), From a7ebaa050643b44a79abff5a77878a339637aff0 Mon Sep 17 00:00:00 2001 From: Abigail McCarthy Date: Mon, 16 May 2022 09:39:54 -0400 Subject: [PATCH 14/28] Update wording and add more useful links Signed-off-by: Abigail McCarthy --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index da18b502a..a3a698c68 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,11 @@ The following is a list of the supported Kubernetes versions for each Velero ver | 1.5 | 1.12-1.21 || | 1.4 | 1.10-1.21 | | -The Velero maintainers are continuously working to expand testing coverage, but are not able to test every combination of Velero and supported Kubernetes for each Velero release. The table above is meant to track the current testing coverage and the expected supported Kubernetes versions and configurations. +Velero supports IPv4, IPv6, and dual stack environments. Support for this was tested against Velero v1.8. -Velero also supports IPv4, IPv6, and dual stack environments. +The Velero maintainers are continuously working to expand testing coverage, but are not able to test every combination of Velero and supported Kubernetes versions for each Velero release. The table above is meant to track the current testing coverage and the expected supported Kubernetes versions for each Velero version. If you have a question about test coverage before v1.9, please reach out in the [#velero-users](https://kubernetes.slack.com/archives/C6VCGP4MT) Slack channel. -If you are interested in using a different version of Kubernetes with a given Velero version, we'd recommend that you perform testing before installing or upgrading your environment. - -For full information around capabilities within a release, also see the Velero [release notes](https://github.com/vmware-tanzu/velero/releases) and Kubernetes [release notes](https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG). +If you are interested in using a different version of Kubernetes with a given Velero version, we'd recommend that you perform testing before installing or upgrading your environment. For full information around capabilities within a release, also see the Velero [release notes](https://github.com/vmware-tanzu/velero/releases) or Kubernetes [release notes](https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG). See the Velero [support page](https://velero.io/docs/latest/support-process/) for information about supported versions of Velero. [1]: https://github.com/vmware-tanzu/velero/workflows/Main%20CI/badge.svg [2]: https://github.com/vmware-tanzu/velero/actions?query=workflow%3A"Main+CI" From be040fca39c83f01c75a622cff8edcb8299f0866 Mon Sep 17 00:00:00 2001 From: Abigail McCarthy Date: Mon, 16 May 2022 13:27:51 -0400 Subject: [PATCH 15/28] Update cluster migration scenario with more details Signed-off-by: Abigail McCarthy --- site/content/docs/main/migration-case.md | 68 +++++++++++++++++------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/site/content/docs/main/migration-case.md b/site/content/docs/main/migration-case.md index f9ec0a57e..c6de64f7b 100644 --- a/site/content/docs/main/migration-case.md +++ b/site/content/docs/main/migration-case.md @@ -3,52 +3,85 @@ title: "Cluster migration" layout: docs --- -Velero can help you port your resources from one cluster to another, as long as you point each Velero instance to the same cloud object storage location. +Velero's backup and restore capabilities make it a valuable tool for migrating your data between clusters, helping you perform many common workflows such as upgrading Kubernetes versions or disaster recovery. Cluster migration with Velero is based on Velero's [object storage sync](how-velero-works.md#object-storage-sync) functionality, which is responsible for syncing Velero resources from your designated object storage to your cluster. This means that to perform cluster migration with Velero you must point each Velero instance running on clusters involved with the migration to the same cloud object storage location. -## Migration Limitations +This page outlines a cluster migration scenario and some common configurations you will need to start using Velero to begin migrating data. + +## Before migrating your cluster Before migrating you should consider the following, -* Velero does not natively support the migration of persistent volumes snapshots across cloud providers. If you would like to migrate volume data between cloud platforms, enable [restic][2], which will backup volume contents at the filesystem level. +* Velero does not natively support the migration of persistent volumes snapshots across cloud providers. If you would like to migrate volume data between cloud platforms, enable [restic](restic.md), which will backup volume contents at the filesystem level. * Velero doesn't support restoring into a cluster with a lower Kubernetes version than where the backup was taken. * Migrating workloads across clusters that are not running the same version of Kubernetes might be possible, but some factors need to be considered before migration, including the compatibility of API groups between clusters for each custom resource. If a Kubernetes version upgrade breaks the compatibility of core/native API groups, migrating with Velero will not be possible without first updating the impacted custom resources. For more information about API group versions, please see [EnableAPIGroupVersions](enable-api-group-versions-feature.md). -* The Velero plugin for AWS and Azure does not support migrating data between regions. If you need to do this, you must use [restic][2]. +* The Velero plugin for AWS and Azure does not support migrating data between regions. If you need to do this, you must use [restic](restic.md). ## Migration Scenario -This scenario assumes that your clusters are hosted by the same cloud provider +This scenario steps through the migration of resources from Cluster 1 to Cluster 2. In this scenario, both clusters are using the same cloud provider, AWS, and Velero's [AWS plugin](https://github.com/vmware-tanzu/velero-plugin-for-aws). -1. *(Cluster 1)* Assuming you haven't already been checkpointing your data with the Velero `schedule` operation, you need to first back up your entire cluster (replacing `` as desired): +1. On Cluster 1, make sure Velero is installed and points to an object storage location using the `--bucket` flag. + + ``` + velero install --provider aws --image velero/velero:v1.8.0 --plugins velero/velero-plugin-for-aws:v1.4.0 --bucket velero-migration-demo --secret-file xxxx/aws-credentials-cluster1 --backup-location-config region=us-east-2 --snapshot-location-config region=us-east-2 + ``` + + During installation, Velero creates a Backup Storage Location called `default` inside the `--bucket` your provided in the install command, in this case `velero-migration-demo`. This is the location that Velero will use to store backups. Running `velero backup-location get` will show the backup location of Cluster 1. + + + ``` + velero backup-location get + NAME PROVIDER BUCKET/PREFIX PHASE LAST VALIDATED ACCESS MODE DEFAULT + default aws velero-migration-demo Available 2022-05-13 13:41:30 +0800 CST ReadWrite true + ``` + +1. Still on Cluster 1, make sure you have a backup of your cluster. Replace `` with a name for your back up. ``` velero backup create ``` - The default backup retention period, expressed as TTL (time to live), is 30 days (720 hours); you can use the `--ttl ` flag to change this as necessary. See [how velero works][1] for more information about backup expiry. + Alternatively, you can create a [scheduled back up](https://velero.io/docs/main/backup-reference/#schedule-a-backup) of your data with the Velero `schedule` operation. This is the recommended way to make sure your data is automatically backed up according to the schedule you define. -1. *(Cluster 2)* Configure `BackupStorageLocations` and `VolumeSnapshotLocations`, pointing to the locations used by *Cluster 1*, using `velero backup-location create` and `velero snapshot-location create`. Make sure to configure the `BackupStorageLocations` as read-only - by using the `--access-mode=ReadOnly` flag for `velero backup-location create`. + The default backup retention period, expressed as TTL (time to live), is 30 days (720 hours); you can use the `--ttl ` flag to change this as necessary. See [how velero works](how-velero-works.md#set-a-backup-to-expire) for more information about backup expiry. -1. *(Cluster 2)* Make sure that the Velero Backup object is created. Velero resources are synchronized with the backup files in cloud storage. +1. On Cluster 2, make sure that Velero is installed. Note that the install command below has the same `region` and `--bucket` location as the install command for Cluster 1. The Velero plugin for AWS does not support migrating data between regions. + + ``` + velero install --provider aws --image velero/velero:v1.8.0 --plugins velero/velero-plugin-for-aws:v1.4.0 --bucket velero-migration-demo --secret-file xxxx/aws-credentials-cluster2 --backup-location-config region=us-east-2 --snapshot-location-config region=us-east-2 + ``` + + Alternatively you could configure `BackupStorageLocations` or `VolumeSnapshotLocations` after installing Velero on Cluster 2, pointing to the `--bucket` location used by Cluster 1. To do this you can use to `velero backup-location create` and `velero snapshot-location create` commands. + + ``` + velero backup-location create bsl --provider aws --bucket velero-migration-demo --config region=us-east-2 --access-mode=ReadOnly + ``` + + Make sure to configure the `BackupStorageLocations` as read-only + by using the `--access-mode=ReadOnly` flag for `velero backup-location create`. See `velero backup-location –help` for more information about the available flags for this command. + +1. Continuing on Cluster 2, make sure that the Velero Backup object created on Cluster 1 is available. `` should be the same name used to create your backup of Cluster 1. ``` velero backup describe ``` - **Note:** The default sync interval is 1 minute, so make sure to wait before checking. You can configure this interval with the `--backup-sync-period` flag to the Velero server. + Velero resources are [synchronized](how-velero-works.md#object-storage-sync) with the backup files in object storage. This means that the Velero resources created by Cluster 1's backup will be synced to Cluster 2 through the shared Backup Storage Location. Once the sync occurs, you will be able to access the back up from Cluster 1 on Cluster 2 using Velero commands. The default sync interval is 1 minute, so you may need to wait before checking for the back up's availability on Cluster 2. You can configure this interval with the `--backup-sync-period` flag to the Velero server on Cluster 2. -1. *(Cluster 2)* Once you have confirmed that the right Backup (``) is now present, you can restore everything with: +1. On Cluster 2, once you have confirmed that the right back up is available, you can restore everything to Cluster 2. ``` velero restore create --from-backup ``` + Make sure `` is the same back up name from Cluster 1. + ## Verify Both Clusters -Check that the second cluster is behaving as expected: +Check that the Cluster 2 is behaving as expected: -1. *(Cluster 2)* Run: +1. On Cluster 2, run: ``` velero restore get @@ -60,9 +93,6 @@ Check that the second cluster is behaving as expected: velero restore describe ``` + Your data that was backed up from Cluster 1 should now be available on Cluster 2. + If you encounter issues, make sure that Velero is running in the same namespace in both clusters. - - - -[1]: how-velero-works.md#set-a-backup-to-expire -[2]: restic.md From 3db40a58a4ff89485e5a3e936318f71004896cfc Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Mon, 16 May 2022 11:30:40 +0800 Subject: [PATCH 16/28] Make velero completion zsh command output can be used by `source` command. Signed-off-by: Xun Jiang --- changelogs/unreleased/4914-jxun | 1 + pkg/cmd/cli/completion/completion.go | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/4914-jxun diff --git a/changelogs/unreleased/4914-jxun b/changelogs/unreleased/4914-jxun new file mode 100644 index 000000000..84db5b83f --- /dev/null +++ b/changelogs/unreleased/4914-jxun @@ -0,0 +1 @@ +Make velero completion zsh command output can be used by `source` command. \ No newline at end of file diff --git a/pkg/cmd/cli/completion/completion.go b/pkg/cmd/cli/completion/completion.go index 800804b98..ee1c28509 100644 --- a/pkg/cmd/cli/completion/completion.go +++ b/pkg/cmd/cli/completion/completion.go @@ -66,7 +66,15 @@ $ velero completion fish > ~/.config/fish/completions/velero.fish case "bash": cmd.Root().GenBashCompletion(os.Stdout) case "zsh": - cmd.Root().GenZshCompletion(os.Stdout) + // # fix #4912 + // cobra does not support zsh completion ouptput used by source command + // according to https://github.com/spf13/cobra/issues/1529 + // Need to append compdef manually to do that. + zshHead := "#compdef velero\ncompdef _velero velero\n" + out := os.Stdout + out.Write([]byte(zshHead)) + + cmd.Root().GenZshCompletion(out) case "fish": cmd.Root().GenFishCompletion(os.Stdout, true) default: From bcef5e1d5e98a39fb0e7b693f052babd5c13b866 Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Tue, 17 May 2022 10:39:14 -0300 Subject: [PATCH 17/28] Refactor to simplify Signed-off-by: Rafael Leal --- pkg/restore/restore.go | 53 ++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index 8fdc014da..57f8c9151 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -1128,13 +1128,13 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso } } - // Clear out non-core metadata fields. - if obj, err = resetMetadata(obj); err != nil { + objStatus, statusFieldExists, statusFieldErr := unstructured.NestedFieldCopy(obj.Object, "status") + // Clear out non-core metadata fields and status. + if obj, err = resetMetadataAndStatus(obj); err != nil { errs.Add(namespace, err) return warnings, errs } - shouldRestoreStatus := ctx.resourceStatusIncludesExcludes.ShouldInclude(groupResource.String()) ctx.log.Infof("restore status includes excludes: %+v", ctx.resourceStatusIncludesExcludes) @@ -1247,17 +1247,6 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso // and which backup they came from. addRestoreLabels(obj, ctx.restore.Name, ctx.restore.Spec.BackupName) - // Clear out status. - objWithoutStatus := obj.DeepCopy() - if objWithoutStatus, err = resetStatus(objWithoutStatus); err != nil { - errs.Add(namespace, err) - return warnings, errs - } - if !shouldRestoreStatus { - ctx.log.Infof("Resetting status for obj %s/%s", obj.GetKind(), obj.GetName()) - obj = objWithoutStatus - } - ctx.log.Infof("Attempting to restore %s: %v", obj.GroupVersionKind().Kind, name) createdObj, restoreErr := resourceClient.Create(obj) isAlreadyExistsError, err := isAlreadyExistsError(ctx, obj, restoreErr, resourceClient) @@ -1273,18 +1262,12 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso return warnings, errs } // Remove insubstantial metadata. - fromCluster, err = resetMetadata(fromCluster) + fromCluster, err = resetMetadataAndStatus(fromCluster) if err != nil { ctx.log.Infof("Error trying to reset metadata for %s: %v", kube.NamespaceAndName(obj), err) warnings.Add(namespace, err) return warnings, errs } - fromCluster, err = resetStatus(fromCluster) - if err != nil { - ctx.log.Infof("Error trying to reset status for %s: %v", kube.NamespaceAndName(obj), err) - warnings.Add(namespace, err) - return warnings, errs - } // We know the object from the cluster won't have the backup/restore name // labels, so copy them from the object we attempted to restore. @@ -1292,7 +1275,7 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso addRestoreLabels(fromCluster, labels[velerov1api.RestoreNameLabel], labels[velerov1api.BackupNameLabel]) fromClusterWithLabels := fromCluster.DeepCopy() // saving the in-cluster object so that we can create label patch if overall patch fails - if !equality.Semantic.DeepEqual(fromCluster, objWithoutStatus) { + if !equality.Semantic.DeepEqual(fromCluster, obj) { switch groupResource { case kuberesource.ServiceAccounts: desired, err := mergeServiceAccounts(fromCluster, obj) @@ -1381,8 +1364,20 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso return warnings, errs } + shouldRestoreStatus := ctx.resourceStatusIncludesExcludes.ShouldInclude(groupResource.String()) + if shouldRestoreStatus && statusFieldErr != nil { + err := fmt.Errorf("could not get status to be restored %s: %v", kube.NamespaceAndName(obj), statusFieldErr) + ctx.log.Errorf(err.Error()) + errs.Add(namespace, err) + return warnings, errs + } // if it should restore status, run a UpdateStatus - if shouldRestoreStatus { + if statusFieldExists && shouldRestoreStatus { + if err := unstructured.SetNestedField(obj.Object, objStatus, "status"); err != nil { + ctx.log.Errorf("could not set status field %s: %v", kube.NamespaceAndName(obj), err) + errs.Add(namespace, err) + return warnings, errs + } obj.SetResourceVersion(createdObj.GetResourceVersion()) updated, err := resourceClient.UpdateStatus(obj, metav1.UpdateOptions{}) if err != nil { @@ -1705,6 +1700,18 @@ func resetStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, er return obj, nil } +func resetMetadataAndStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { + newObj, err := resetMetadata(obj) + if err != nil { + return nil, err + } + newObj, err = resetStatus(obj) + if err != nil { + return nil, err + } + return newObj, nil +} + // addRestoreLabels labels the provided object with the restore name and the // restored backup's name. func addRestoreLabels(obj metav1.Object, restoreName, backupName string) { From 0e649b9d3ffbbed0f7457933918f364392c71d69 Mon Sep 17 00:00:00 2001 From: Abigail McCarthy Date: Tue, 17 May 2022 12:09:49 -0400 Subject: [PATCH 18/28] Fix typos Signed-off-by: Abigail McCarthy --- site/content/docs/main/migration-case.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/site/content/docs/main/migration-case.md b/site/content/docs/main/migration-case.md index c6de64f7b..027083eab 100644 --- a/site/content/docs/main/migration-case.md +++ b/site/content/docs/main/migration-case.md @@ -3,7 +3,7 @@ title: "Cluster migration" layout: docs --- -Velero's backup and restore capabilities make it a valuable tool for migrating your data between clusters, helping you perform many common workflows such as upgrading Kubernetes versions or disaster recovery. Cluster migration with Velero is based on Velero's [object storage sync](how-velero-works.md#object-storage-sync) functionality, which is responsible for syncing Velero resources from your designated object storage to your cluster. This means that to perform cluster migration with Velero you must point each Velero instance running on clusters involved with the migration to the same cloud object storage location. +Velero's backup and restore capabilities make it a valuable tool for migrating your data between clusters. Cluster migration with Velero is based on Velero's [object storage sync](how-velero-works.md#object-storage-sync) functionality, which is responsible for syncing Velero resources from your designated object storage to your cluster. This means that to perform cluster migration with Velero you must point each Velero instance running on clusters involved with the migration to the same cloud object storage location. This page outlines a cluster migration scenario and some common configurations you will need to start using Velero to begin migrating data. @@ -36,13 +36,13 @@ This scenario steps through the migration of resources from Cluster 1 to Cluster default aws velero-migration-demo Available 2022-05-13 13:41:30 +0800 CST ReadWrite true ``` -1. Still on Cluster 1, make sure you have a backup of your cluster. Replace `` with a name for your back up. +1. Still on Cluster 1, make sure you have a backup of your cluster. Replace `` with a name for your backup. ``` velero backup create ``` - Alternatively, you can create a [scheduled back up](https://velero.io/docs/main/backup-reference/#schedule-a-backup) of your data with the Velero `schedule` operation. This is the recommended way to make sure your data is automatically backed up according to the schedule you define. + Alternatively, you can create a [scheduled backup](https://velero.io/docs/main/backup-reference/#schedule-a-backup) of your data with the Velero `schedule` operation. This is the recommended way to make sure your data is automatically backed up according to the schedule you define. The default backup retention period, expressed as TTL (time to live), is 30 days (720 hours); you can use the `--ttl ` flag to change this as necessary. See [how velero works](how-velero-works.md#set-a-backup-to-expire) for more information about backup expiry. @@ -52,7 +52,7 @@ This scenario steps through the migration of resources from Cluster 1 to Cluster velero install --provider aws --image velero/velero:v1.8.0 --plugins velero/velero-plugin-for-aws:v1.4.0 --bucket velero-migration-demo --secret-file xxxx/aws-credentials-cluster2 --backup-location-config region=us-east-2 --snapshot-location-config region=us-east-2 ``` - Alternatively you could configure `BackupStorageLocations` or `VolumeSnapshotLocations` after installing Velero on Cluster 2, pointing to the `--bucket` location used by Cluster 1. To do this you can use to `velero backup-location create` and `velero snapshot-location create` commands. + Alternatively you could configure `BackupStorageLocations` and `VolumeSnapshotLocations` after installing Velero on Cluster 2, pointing to the `--bucket` location and `region` used by Cluster 1. To do this you can use to `velero backup-location create` and `velero snapshot-location create` commands. ``` velero backup-location create bsl --provider aws --bucket velero-migration-demo --config region=us-east-2 --access-mode=ReadOnly @@ -61,21 +61,27 @@ This scenario steps through the migration of resources from Cluster 1 to Cluster Make sure to configure the `BackupStorageLocations` as read-only by using the `--access-mode=ReadOnly` flag for `velero backup-location create`. See `velero backup-location –help` for more information about the available flags for this command. + ``` + velero snapshot-location create vsl --provider aws --config region=us-east-2 + ``` + See `velero snapshot-location –help` for more information about the available flags for this command. + + 1. Continuing on Cluster 2, make sure that the Velero Backup object created on Cluster 1 is available. `` should be the same name used to create your backup of Cluster 1. ``` velero backup describe ``` - Velero resources are [synchronized](how-velero-works.md#object-storage-sync) with the backup files in object storage. This means that the Velero resources created by Cluster 1's backup will be synced to Cluster 2 through the shared Backup Storage Location. Once the sync occurs, you will be able to access the back up from Cluster 1 on Cluster 2 using Velero commands. The default sync interval is 1 minute, so you may need to wait before checking for the back up's availability on Cluster 2. You can configure this interval with the `--backup-sync-period` flag to the Velero server on Cluster 2. + Velero resources are [synchronized](how-velero-works.md#object-storage-sync) with the backup files in object storage. This means that the Velero resources created by Cluster 1's backup will be synced to Cluster 2 through the shared Backup Storage Location. Once the sync occurs, you will be able to access the backup from Cluster 1 on Cluster 2 using Velero commands. The default sync interval is 1 minute, so you may need to wait before checking for the backup's availability on Cluster 2. You can configure this interval with the `--backup-sync-period` flag to the Velero server on Cluster 2. -1. On Cluster 2, once you have confirmed that the right back up is available, you can restore everything to Cluster 2. +1. On Cluster 2, once you have confirmed that the right backup is available, you can restore everything to Cluster 2. ``` velero restore create --from-backup ``` - Make sure `` is the same back up name from Cluster 1. + Make sure `` is the same backup name from Cluster 1. ## Verify Both Clusters From c6d568ad1248154151999eab8a6df3092fbf65e9 Mon Sep 17 00:00:00 2001 From: Abigail McCarthy Date: Tue, 17 May 2022 23:02:28 -0400 Subject: [PATCH 19/28] Make updates from review Signed-off-by: Abigail McCarthy --- site/content/docs/main/migration-case.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/content/docs/main/migration-case.md b/site/content/docs/main/migration-case.md index 027083eab..afb3a3e2a 100644 --- a/site/content/docs/main/migration-case.md +++ b/site/content/docs/main/migration-case.md @@ -58,8 +58,8 @@ This scenario steps through the migration of resources from Cluster 1 to Cluster velero backup-location create bsl --provider aws --bucket velero-migration-demo --config region=us-east-2 --access-mode=ReadOnly ``` - Make sure to configure the `BackupStorageLocations` as read-only - by using the `--access-mode=ReadOnly` flag for `velero backup-location create`. See `velero backup-location –help` for more information about the available flags for this command. + Its recommended that you configure the `BackupStorageLocations` as read-only + by using the `--access-mode=ReadOnly` flag for `velero backup-location create`. This will make sure that the backup is not deleted from the object store by mistake during the restore. See `velero backup-location –help` for more information about the available flags for this command. ``` velero snapshot-location create vsl --provider aws --config region=us-east-2 From 95ccbb617a24f57438d33a1d24298cd5080adb84 Mon Sep 17 00:00:00 2001 From: Abigail McCarthy Date: Wed, 18 May 2022 23:20:00 -0400 Subject: [PATCH 20/28] Update docs for flag to skip TLS validation Signed-off-by: Abigail McCarthy --- site/content/docs/main/self-signed-certificates.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/site/content/docs/main/self-signed-certificates.md b/site/content/docs/main/self-signed-certificates.md index 0bb55be8c..ae4f3f854 100644 --- a/site/content/docs/main/self-signed-certificates.md +++ b/site/content/docs/main/self-signed-certificates.md @@ -46,3 +46,12 @@ Error 116 represents certificate required as seen here in [error codes](https:// Velero as a client does not include its certificate while performing SSL handshake with the server. From [TLS 1.3 spec](https://tools.ietf.org/html/rfc8446), verifying client certificate is optional on the server. You will need to change this setting on the server to make it work. + + +## Skipping TLS verification + +**Note:** The `--insecure-skip-tls-verify` flag is insecure and susceptible to man-in-the-middle attacks and meant to help your testing and developing scenarios in an on-premise environment. Using this flag in production is not recommended. + +Velero provides a way for you to skip TLS verification on the object store by passing the `--insecure-skip-tls-verify` flag with Velero commands. If true, the object store's TLS certificate will not be checked for validity before Velero connects to the object store or Restic repo. You can permanently skip TLS verification for an object store by setting `Spec.Config.InsecureSkipTLSVerify` to true in the [BackupStorageLocation](api-types/backupstoragelocation.md) CRD. + +This flag is currently only implemented for use with AWS provider plugin and Restic. From 20da7c8bcacf44fb5be74e38884cb18f23c02ed0 Mon Sep 17 00:00:00 2001 From: Abigail McCarthy Date: Thu, 19 May 2022 10:12:27 -0400 Subject: [PATCH 21/28] Include moer details Signed-off-by: Abigail McCarthy --- site/content/docs/main/self-signed-certificates.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/site/content/docs/main/self-signed-certificates.md b/site/content/docs/main/self-signed-certificates.md index ae4f3f854..acf2019cd 100644 --- a/site/content/docs/main/self-signed-certificates.md +++ b/site/content/docs/main/self-signed-certificates.md @@ -52,6 +52,14 @@ You will need to change this setting on the server to make it work. **Note:** The `--insecure-skip-tls-verify` flag is insecure and susceptible to man-in-the-middle attacks and meant to help your testing and developing scenarios in an on-premise environment. Using this flag in production is not recommended. -Velero provides a way for you to skip TLS verification on the object store by passing the `--insecure-skip-tls-verify` flag with Velero commands. If true, the object store's TLS certificate will not be checked for validity before Velero connects to the object store or Restic repo. You can permanently skip TLS verification for an object store by setting `Spec.Config.InsecureSkipTLSVerify` to true in the [BackupStorageLocation](api-types/backupstoragelocation.md) CRD. +Velero provides a way for you to skip TLS verification on the object store when using the [AWS provider plugin](https://github.com/vmware-tanzu/velero-plugin-for-aws) or [Restic](restic.md) by passing the `--insecure-skip-tls-verify` flag with the following Velero commands, -This flag is currently only implemented for use with AWS provider plugin and Restic. +* velero backup describe +* velero backup download +* velero backup logs +* velero restore describe +* velero restore log + +If true, the object store's TLS certificate will not be checked for validity before Velero connects to the object store or Restic repo. You can permanently skip TLS verification for an object store by setting `Spec.Config.InsecureSkipTLSVerify` to true in the [BackupStorageLocation](api-types/backupstoragelocation.md) CRD. + +Note that Velero's Restic integration uses Restic commands to do data transfer between object store and Kubernetes cluster disks. This means that when you specify `--insecure-skip-tls-verify` in Velero operations that involve interacting with Restic, Velero will add the Restic global command parameter `--insecure-skip` to Restic commands. From 0aafba2cd855a0a78996b2635f92cb636f1b2f7b Mon Sep 17 00:00:00 2001 From: Scott Seago Date: Thu, 19 May 2022 11:11:14 -0400 Subject: [PATCH 22/28] Propose Shubham Pampattiwar as a maintainer Shubham Pampattiwar has made several contributions to Velero, most recently in designing and implementing two v1.9 features, including the following: - [Add design for enabling multiple label support](https://github.com/vmware-tanzu/velero/pull/4619) - [Add multiple label selector support to Velero Backup and Restore APIs](https://github.com/vmware-tanzu/velero/pull/4650) - [Add design for enabling support for ExistingResourcePolicy to restore API](https://github.com/vmware-tanzu/velero/pull/4613) - [Add existingResourcePolicy to Restore API](https://github.com/vmware-tanzu/velero/pull/4628) Shubham has also been driving forward the data mover requirements and design discussions for velero 1.10: - [Add datamover design](https://github.com/vmware-tanzu/velero/pull/4768) Signed-off-by: Scott Seago --- .github/auto-assignees.yml | 1 + MAINTAINERS.md | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/auto-assignees.yml b/.github/auto-assignees.yml index 346fcc9aa..282591d72 100644 --- a/.github/auto-assignees.yml +++ b/.github/auto-assignees.yml @@ -15,6 +15,7 @@ reviewers: - ywk253100 - blackpiglet - qiuming-best + - shubham-pampattiwar tech-writer: - a-mccarthy diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 561c0ee96..2819a77e8 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -12,6 +12,7 @@ | Wenkai Yin | [ywk253100](https://github.com/ywk253100) | [VMware](https://www.github.com/vmware/) | | Xun Jiang | [blackpiglet](https://github.com/blackpiglet) | [VMware](https://www.github.com/vmware/) | | Ming Qiu | [qiuming-best](https://github.com/qiuming-best) | [VMware](https://www.github.com/vmware/) | +| Shubham Pampattiwar | [shubham-pampattiwar](https://github.com/shubham-pampattiwar) | [OpenShift](https://github.com/openshift) ## Emeritus Maintainers * Adnan Abdulhussein ([prydonius](https://github.com/prydonius)) From 131c8a920f0e205dff9c245df8490b8292991e50 Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Thu, 19 May 2022 17:36:21 -0300 Subject: [PATCH 23/28] Remove break line Signed-off-by: Rafael Leal --- pkg/restore/restore.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index 57f8c9151..76e8a3658 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -1135,7 +1135,6 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso return warnings, errs } - ctx.log.Infof("restore status includes excludes: %+v", ctx.resourceStatusIncludesExcludes) for _, action := range ctx.getApplicableActions(groupResource, namespace) { From 61b0d990fa981edc01839af1768690548b57cac1 Mon Sep 17 00:00:00 2001 From: Abigail McCarthy Date: Thu, 19 May 2022 22:37:02 -0400 Subject: [PATCH 24/28] fix flag typo Signed-off-by: Abigail McCarthy --- site/content/docs/main/self-signed-certificates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/docs/main/self-signed-certificates.md b/site/content/docs/main/self-signed-certificates.md index acf2019cd..2aab5c1b9 100644 --- a/site/content/docs/main/self-signed-certificates.md +++ b/site/content/docs/main/self-signed-certificates.md @@ -62,4 +62,4 @@ Velero provides a way for you to skip TLS verification on the object store when If true, the object store's TLS certificate will not be checked for validity before Velero connects to the object store or Restic repo. You can permanently skip TLS verification for an object store by setting `Spec.Config.InsecureSkipTLSVerify` to true in the [BackupStorageLocation](api-types/backupstoragelocation.md) CRD. -Note that Velero's Restic integration uses Restic commands to do data transfer between object store and Kubernetes cluster disks. This means that when you specify `--insecure-skip-tls-verify` in Velero operations that involve interacting with Restic, Velero will add the Restic global command parameter `--insecure-skip` to Restic commands. +Note that Velero's Restic integration uses Restic commands to do data transfer between object store and Kubernetes cluster disks. This means that when you specify `--insecure-skip-tls-verify` in Velero operations that involve interacting with Restic, Velero will add the Restic global command parameter `--insecure-tls` to Restic commands. From e0e3016efa2e9e5221cce8a2d2cf35efb3196c5a Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Mon, 23 May 2022 17:53:32 -0300 Subject: [PATCH 25/28] Cleanup resetStatus Signed-off-by: Rafael Leal --- pkg/restore/restore.go | 15 +++++---------- pkg/restore/restore_test.go | 12 +++--------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index 76e8a3658..e4834ecde 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -1009,7 +1009,6 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso } if groupResource == kuberesource.PersistentVolumes { - resetStatus(obj) switch { case hasSnapshot(name, ctx.volumeSnapshots): oldName := obj.GetName() @@ -1694,21 +1693,17 @@ func resetMetadata(obj *unstructured.Unstructured) (*unstructured.Unstructured, return obj, nil } -func resetStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - delete(obj.UnstructuredContent(), "status") - return obj, nil +func resetStatus(obj *unstructured.Unstructured) { + unstructured.RemoveNestedField(obj.UnstructuredContent(), "status") } func resetMetadataAndStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { - newObj, err := resetMetadata(obj) + _, err := resetMetadata(obj) if err != nil { return nil, err } - newObj, err = resetStatus(obj) - if err != nil { - return nil, err - } - return newObj, nil + resetStatus(obj) + return obj, nil } // addRestoreLabels labels the provided object with the restore name and the diff --git a/pkg/restore/restore_test.go b/pkg/restore/restore_test.go index 87528a627..7655253d1 100644 --- a/pkg/restore/restore_test.go +++ b/pkg/restore/restore_test.go @@ -2847,30 +2847,24 @@ func TestResetStatus(t *testing.T) { tests := []struct { name string obj *unstructured.Unstructured - expectedErr bool expectedRes *unstructured.Unstructured }{ { - name: "no metadata don't cause error", + name: "no status don't cause error", obj: &unstructured.Unstructured{}, - expectedErr: false, expectedRes: &unstructured.Unstructured{}, }, { name: "remove status", obj: NewTestUnstructured().WithMetadata().WithStatus().Unstructured, - expectedErr: false, expectedRes: NewTestUnstructured().WithMetadata().Unstructured, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - res, err := resetStatus(test.obj) - - if assert.Equal(t, test.expectedErr, err != nil) { - assert.Equal(t, test.expectedRes, res) - } + resetStatus(test.obj) + assert.Equal(t, test.expectedRes, test.obj) }) } } From 8a156d69b97cad9b506bac98b4aa0802e5e8341a Mon Sep 17 00:00:00 2001 From: Abigail McCarthy Date: Mon, 23 May 2022 22:19:10 -0400 Subject: [PATCH 26/28] Add details about using multiple volume snapshot locations and restic Signed-off-by: Abigail McCarthy --- .../docs/main/customize-installation.md | 26 ++++++++++++++++--- site/content/docs/main/locations.md | 2 ++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/site/content/docs/main/customize-installation.md b/site/content/docs/main/customize-installation.md index e82002eec..b90300f82 100644 --- a/site/content/docs/main/customize-installation.md +++ b/site/content/docs/main/customize-installation.md @@ -25,11 +25,9 @@ If you've already run `velero install` without the `--use-restic` flag, you can ## Default Pod Volume backup to restic -By default, `velero install` does not enable use of restic to take backups of all pod volumes. An annotation has to be applied on every pod which contains volumes to be backed up by restic. +By default, `velero install` does not enable the use of restic to take backups of all pod volumes. You must apply an [annotation](restic.md/#using-opt-in-pod-volume-backup) to every pod which contains volumes for Velero to use restic for the backup. -To backup all pod volumes using restic without having to apply annotation on the pod, run the `velero install` command with the `--default-volumes-to-restic` flag. - -Using this flag requires restic integration to be enabled with the `--use-restic` flag. Please refer to the [restic integration][3] page for more information. +If you are planning to only use restic for volume backups, you can run the `velero install` command with the `--default-volumes-to-restic` flag. This will default all pod volumes backups to use restic without having to apply annotations to pods. Note that when this flag is set during install, Velero will always try to use restic to perform the backup, even want an individual backup to use volume snapshots, by setting the `--snapshot-volumes` flag in the `backup create` command. Alternatively, you can set the `--default-volumes-to-restic` on an individual backup to to make sure Velero uses Restic for each volume being backed up. ## Enable features @@ -173,6 +171,26 @@ However, `velero install` only supports configuring at most one backup storage l To configure additional locations after running `velero install`, use the `velero backup-location create` and/or `velero snapshot-location create` commands along with provider-specific configuration. Use the `--help` flag on each of these commands for more details. +### Set default backup storage location or volume snapshot locations + +When performing backups, Velero needs to know where to backup your data. This means that if you configure multiple locations, you must specify the location Velero should use each time you run `velero backup create`, or you can set a default backup storage location or default volume snapshot locations. If you only have one backup storage llocation or volume snapshot location set for a provider, Velero will automatically use that location as the default. + +Set a default backup storage location by passing a `--default` flag with when running `velero backup-location create`. + +``` +velero backup-location create backups-primary \ + --provider aws \ + --bucket velero-backups \ + --config region=us-east-1 \ + --default +``` + +You can set a default volume snapshot location for each of your volume snapshot providers using the `--default-volume-snapshot-locations` flag on the `velero server` command. + +``` +velero server --default-volume-snapshot-locations=":,:" +``` + ## Do not configure a backup storage location during install If you need to install Velero without a default backup storage location (without specifying `--bucket` or `--provider`), the `--no-default-backup-location` flag is required for confirmation. diff --git a/site/content/docs/main/locations.md b/site/content/docs/main/locations.md index 2f54077dd..d5dbc710a 100644 --- a/site/content/docs/main/locations.md +++ b/site/content/docs/main/locations.md @@ -41,6 +41,8 @@ This configuration design enables a number of different use cases, including: - Velero's compression for object metadata is limited, using Golang's tar implementation. In most instances, Kubernetes objects are limited to 1.5MB in size, but many don't approach that, meaning that compression may not be necessary. Note that restic has not yet implemented compression, but does have de-deduplication capabilities. +- If you have [multiple](customize-installation.md/#configure-more-than-one-storage-location-for-backups-or-volume-snapshots) `VolumeSnapshotLocations` configured for a provider, you must always specify a valid `VolumeSnapshotLocation` when creating a backup, even if you are using [Restic](restic.md) for volume backups. You can optionally decide to set the [`--default-volume-snapshot-locations`](customize-locations.md#set-default-backup-storage-location-or-volume-snapshot-locations) flag using the `velero server`, which lists the default `VolumeSnapshotLocation` Velero should use if a `VolumeSnapshotLocation` is not specified when creating a backup. If you only have one `VolumeSnapshotLocation` for a provider, Velero will automatically use that location as the default. + ## Examples Let's look at some examples of how you can use this configuration mechanism to address some common use cases: From 7e8f1dcf6fe3fae11371120f06edd73bdcf153f5 Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Tue, 24 May 2022 00:11:53 -0300 Subject: [PATCH 27/28] Add docs Signed-off-by: Rafael Leal --- site/content/docs/main/api-types/restore.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/site/content/docs/main/api-types/restore.md b/site/content/docs/main/api-types/restore.md index a8d064a6e..ae4354666 100644 --- a/site/content/docs/main/api-types/restore.md +++ b/site/content/docs/main/api-types/restore.md @@ -46,6 +46,21 @@ spec: # or fully-qualified. Optional. excludedResources: - storageclasses.storage.k8s.io + + # restoreStatus selects resources to restore not only the specification, but + # the status of the manifest. This is specially useful for CRDs that maintain + # external references. By default, it excludes all resources. + restoreStatus: + # Array of resources to include in the restore status. Just like above, + # resources may be shortcuts (for example 'po' for 'pods') or fully-qualified. + # If unspecified, no resources are included. Optional. + includedResources: + - workflows + # Array of resources to exclude from the restore status. Resources may be + # shortcuts (for example 'po' for 'pods') or fully-qualified. + # If unspecified, all resources are excluded. Optional. + excludedResources: [] + # Whether or not to include cluster-scoped resources. Valid values are true, false, and # null/unset. If true, all cluster-scoped resources are included (subject to included/excluded # resources and the label selector). If false, no cluster-scoped resources are included. If unset, From 200769a077d337a6536906d75c23c27df75b393f Mon Sep 17 00:00:00 2001 From: Rafael Leal Date: Tue, 24 May 2022 00:14:02 -0300 Subject: [PATCH 28/28] Add changelog Signed-off-by: Rafael Leal --- changelogs/unreleased/4785-RafaeLeal | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/unreleased/4785-RafaeLeal diff --git a/changelogs/unreleased/4785-RafaeLeal b/changelogs/unreleased/4785-RafaeLeal new file mode 100644 index 000000000..450fed9c3 --- /dev/null +++ b/changelogs/unreleased/4785-RafaeLeal @@ -0,0 +1 @@ +Add ability to restore status on selected resources