From 75bb73e1b2773241ae87b2c432a9cb42427aed21 Mon Sep 17 00:00:00 2001 From: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> Date: Thu, 9 Jan 2025 19:23:14 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A0=EF=B8=8F=20[Monorepo]=20PHASE=201=20-?= =?UTF-8?q?=20Add=20Catalogd=20to=20Operator-Controller=20Repository=20(#1?= =?UTF-8?q?542)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Makes codecov-action optional We do not want to fail the job if codecov fails to upload the report due to rate limiting. Signed-off-by: Mikalai Radchuk * Enable dependabot (#125) Signed-off-by: Andy Goldstein * Enable merge queue (#131) Signed-off-by: Andy Goldstein * Switch to using tilt-support repo Signed-off-by: Andy Goldstein * Add DCO information Signed-off-by: Andy Goldstein * Add CI for tilt (#134) Signed-off-by: Andy Goldstein * Enable CatalogMetadataAPI via explicit flag, fix syncing issues (#138) * Setup CODEOWNERS (#140) Signed-off-by: Andy Goldstein * Deprecate the `CatalogMetadataAPI` feature gate (#141) Marking the CatalogMetadataAPI feature gate as Deprecated before introducing the HTTP server as a default mechanism to serve catalog contents Signed-off-by: Rashmi Gottipati * Remove Package and BundleMetadata APIs (#149) Signed-off-by: Joe Lanford * add go-apidiff action (#151) Signed-off-by: Joe Lanford * Store FBC in local directory (#144) closes #113 Signed-off-by: Anik * update demo based on API changes (#154) Signed-off-by: Jordan Keister * Serve locally stored fbc content via an http server (#148) Closes #113 Signed-off-by: Anik * Add metrics to the catalog server (#156) * add metrics to catalogd http server that can be used for calculating the Apdex Score and assess the health of the http server that is serving catalog contents to clients Signed-off-by: Bryce Palmer * quick fixes from review comments Signed-off-by: Bryce Palmer * rename package from server --> metrics Signed-off-by: Bryce Palmer * rename package from server --> metrics Signed-off-by: Bryce Palmer --------- Signed-off-by: Bryce Palmer * (docs): Add docs on fetching contents via HTTP server (#166) * (docs): Add docs on fetching contents via HTTP server Signed-off-by: Bryce Palmer * add curl examples Signed-off-by: Bryce Palmer --------- Signed-off-by: Bryce Palmer Signed-off-by: Bryce Palmer * (refactor): Remove deprecated CatalogMetadata and associated code (#169) * (refactor): Remove deprecated CatalogMetadata and associated code Signed-off-by: Bryce Palmer * go mod tidy Signed-off-by: Bryce Palmer --------- Signed-off-by: Bryce Palmer * (server) Expose content URL on CR status (#168) closes #119 Signed-off-by: Anik * deps: bump kubernetes and operator-registry (#173) Signed-off-by: Joe Lanford * Add RELEASING.md (#176) Add release guide Signed-off-by: Catherine Chan-Tse * Add contribution guide (#165) * Add contributing guide to catalogd Signed-off-by: Rashmi Gottipati * Address review comments Signed-off-by: Rashmi Gottipati --------- Signed-off-by: Rashmi Gottipati * Update README with simplified make target ref (#178) Signed-off-by: kevinrizza * add default printer columns (#174) Add default printer columns Signed-off-by: kevinrizza * (cleanup) Kustomization (#183) Closes #155, #160 Signed-off-by: Anik Bhattacharjee * (feature): add direct image registry client `Unpacker` implementation (#145) (feat): direct image registry client unpacker Signed-off-by: Bryce Palmer * (techdebt): refactor catalog controller unit tests (#196) * (techdebt): refactor catalog controller unit tests to no longer use Ginkgo and instead use the native Go testing and testify Signed-off-by: Bryce Palmer * remove rebase detritus, unnecessary IIFE, and featuregate comments/blocks. goimports. Signed-off-by: Bryce Palmer --------- Signed-off-by: Bryce Palmer * Bump golang.org/x/net from 0.10.0 to 0.17.0 (#197) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.10.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/docker/docker from 23.0.1+incompatible to 23.0.3+incompatible (#195) Bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 23.0.1+incompatible to 23.0.3+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v23.0.1...v23.0.3) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * (feature) Implement polling image source in intervals (#185) Implements https://docs.google.com/document/d/1iWSrWL9pYRJ5Ua3VYErkK1Q2lAusBUeDCh66Ew4lDbQ/edit?usp=sharing Closes #180 Signed-off-by: Anik Bhattacharjee * Add GoDoc for Phase (#199) GoDoc for Phase Signed-off-by: Anik Bhattacharjee * (feature): add skip-tls-verify option for image sources (#201) * (feature): add skip-tls-verify option for image sources Signed-off-by: Bryce Palmer * re-generate manifests Signed-off-by: Bryce Palmer --------- Signed-off-by: Bryce Palmer * 🌱 Add PR template with icons & verify job (#205) Add PR template with icons & verify job Signed-off-by: Andy Goldstein * 🌱 Bump github.com/docker/docker from 23.0.3+incompatible to 24.0.7+incompatible (#203) Bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 23.0.3+incompatible to 24.0.7+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v23.0.3...v24.0.7) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :bug: attempt to remove cache entry if unpack fails (#207) (bugfix): attempt to remove cache entry if unpack fails and add a new test case that ensures if the required label is missing from the image, thus failing image unpacking, an error is consistently returned fixes #206 Signed-off-by: Bryce Palmer * 🌱 Prefix dependabot GH actions PRs (#208) Prefix dependabot GH actions PRs Signed-off-by: Andy Goldstein * :seedling: replace e2e Job with client-go ProxyGet() call (#210) (e2e): replace e2e Job with client-go ProxyGet() call Signed-off-by: Bryce Palmer * ✨ Add Ingress overlay to access `Catalog` contents outside of the cluster (#209) * Add Ingress overlay to access `Catalog` contents outside of the cluster Signed-off-by: Rashmi Gottipati * Address review feedback Signed-off-by: Rashmi Gottipati * Address review feedback #1 Signed-off-by: Rashmi Gottipati * Address feedback #2 Signed-off-by: Rashmi Gottipati --------- Signed-off-by: Rashmi Gottipati * 🌱 bump to k8s 1.27.7 (#211) bump to k8s 1.27.7 to ensure catalogd is fully remediated and unaffected by the rapid reset CVE Signed-off-by: Bryce Palmer * :seedling: Remove cert-manager from release note install process (#215) Remove cert-manager from release note install process as cert-manager has not been a requirement for installing catalogd for quite some time. Signed-off-by: Bryce Palmer * :bug: Add enum validation for source type (#214) Add enum validation for source type Signed-off-by: Bryce Palmer * 🌱 updates to enable autogenerated demo, hosted out-of-tree (#212) * updates to support automated demo generation Signed-off-by: Jordan Keister * review updates Signed-off-by: Jordan Keister --------- Signed-off-by: Jordan Keister * :seedling: demo install from published tag (#217) * demo install from published tag Signed-off-by: Jordan Keister * review updates Signed-off-by: Jordan Keister --------- Signed-off-by: Jordan Keister * Bump golang.org/x/crypto from 0.14.0 to 0.17.0 (#218) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.14.0 to 0.17.0. - [Commits](https://github.com/golang/crypto/compare/v0.14.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/go-git/go-git/v5 from 5.4.2 to 5.11.0 (#220) Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.4.2 to 5.11.0. - [Release notes](https://github.com/go-git/go-git/releases) - [Commits](https://github.com/go-git/go-git/compare/v5.4.2...v5.11.0) --- updated-dependencies: - dependency-name: github.com/go-git/go-git/v5 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/containerd/containerd from 1.6.22 to 1.6.26 (#219) Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.6.22 to 1.6.26. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.6.22...v1.6.26) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * (bugfix): bump the catalogserver write timeout to 5 minutes (#223) to allow for fully writing large catalogs contents in the response Signed-off-by: everettraven * (bugfix): add validation for pollInterval duration units (#225) Signed-off-by: everettraven * (chore): bump supported k8s version to 1.28 (#227) bumps controller-runtime --> v0.16.3 bumps k8s.io deps --> v0.28.5 bumps operator-registry --> v1.34.0 updated kind version --> v0.20.0 made kind node image configurable and 1.28 by default updated ginkgo version --> v2.12.0 Signed-off-by: everettraven * Bump github.com/containerd/containerd from 1.7.6 to 1.7.11 (#228) Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.6 to 1.7.11. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.6...v1.7.11) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump golang.org/x/crypto from 0.16.0 to 0.17.0 (#230) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.16.0 to 0.17.0. - [Commits](https://github.com/golang/crypto/compare/v0.16.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * (bugfix): make garbage collection a runnable (#231) and add it to the controller manager. Make it log errors instead of exiting. This prevents crashlooping when there are errors in the garbage collection process. Signed-off-by: everettraven * bumping codecov-action to v4 (#232) * GH Actions: add workflow to add epic issues to OLMv1 project (#233) Signed-off-by: Joe Lanford * Bump google.golang.org/protobuf from 1.31.0 to 1.33.0 (#234) Bumps google.golang.org/protobuf from 1.31.0 to 1.33.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump Go to 1.21 (#237) Signed-off-by: Mikalai Radchuk * bump docker deps to 25.0.5 (#236) * bump kind to 0.22.0 (#238) Signed-off-by: Joe Lanford * remove terminating space in dependabot config file (#245) Signed-off-by: Jordan Keister * make golangci-lint config consistent across repos (#255) Signed-off-by: Joe Lanford * Bump golang.org/x/net from 0.19.0 to 0.23.0 (#244) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.19.0 to 0.23.0. - [Commits](https://github.com/golang/net/compare/v0.19.0...v0.23.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump docker/login-action from 2 to 3 (#246) Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump actions/checkout from 3 to 4 (#247) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/go-logr/logr from 1.3.0 to 1.4.1 (#253) Bumps [github.com/go-logr/logr](https://github.com/go-logr/logr) from 1.3.0 to 1.4.1. - [Release notes](https://github.com/go-logr/logr/releases) - [Changelog](https://github.com/go-logr/logr/blob/master/CHANGELOG.md) - [Commits](https://github.com/go-logr/logr/compare/v1.3.0...v1.4.1) --- updated-dependencies: - dependency-name: github.com/go-logr/logr dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump actions/add-to-project from 0.5.0 to 1.0.1 (#249) Bumps [actions/add-to-project](https://github.com/actions/add-to-project) from 0.5.0 to 1.0.1. - [Release notes](https://github.com/actions/add-to-project/releases) - [Commits](https://github.com/actions/add-to-project/compare/v0.5.0...v1.0.1) --- updated-dependencies: - dependency-name: actions/add-to-project dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump actions/setup-go from 4 to 5 (#250) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump sigs.k8s.io/yaml from 1.3.0 to 1.4.0 (#254) Bumps [sigs.k8s.io/yaml](https://github.com/kubernetes-sigs/yaml) from 1.3.0 to 1.4.0. - [Release notes](https://github.com/kubernetes-sigs/yaml/releases) - [Changelog](https://github.com/kubernetes-sigs/yaml/blob/master/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/yaml/compare/v1.3.0...v1.4.0) --- updated-dependencies: - dependency-name: sigs.k8s.io/yaml dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump kubernetes-sigs/kubebuilder-release-tools (#248) Bumps [kubernetes-sigs/kubebuilder-release-tools](https://github.com/kubernetes-sigs/kubebuilder-release-tools) from 0.4.0 to 0.4.3. - [Release notes](https://github.com/kubernetes-sigs/kubebuilder-release-tools/releases) - [Changelog](https://github.com/kubernetes-sigs/kubebuilder-release-tools/blob/master/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/kubebuilder-release-tools/compare/v0.4.0...v0.4.3) --- updated-dependencies: - dependency-name: kubernetes-sigs/kubebuilder-release-tools dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * OCPBUGS-28230: enforce termination message policy on all platform pods (#260) Signed-off-by: Joe Lanford * bump controller-gen to v0.14.0 (#262) Signed-off-by: Tayler Geiger * ⚠️ Serve catalog over HTTPS (#263) * make catalog server serve catalog contents over HTTPS adds cert-manager as a dependency again to create self-signed certs for the catalog server Signed-off-by: everettraven * fix e2e Signed-off-by: everettraven * Reorganize manifests for cert-manager overlay This allows the use of alternate certificate managers. Signed-off-by: Tayler Geiger * Reconfigure TLS functionality to use Listener Fix a few manifest issues as well. Signed-off-by: Tayler Geiger * Add certwatcher for TLS cert and key from controller-runtime - Add error for missing either tls-key or tls-cert arguments. - Move server creation and configuration to serverutil Signed-off-by: Tayler Geiger * Update README and docs for HTTPS --------- Signed-off-by: everettraven Signed-off-by: Tayler Geiger Co-authored-by: everettraven * Makefile: fix issues with repeated evaluations (#267) * rename Catalog to ClusterCatalog (#268) Signed-off-by: everettraven * ✨ Bump k8s deps to 0.30.0 and go 1.22 (#269) * bump to go 1.22 and k8s 0.30.0 Signed-off-by: everettraven * bump o-reg to tag Signed-off-by: everettraven --------- Signed-off-by: everettraven * :seedling: Bump k8s.io/client-go from 0.30.0 to 0.30.1 (#276) Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 0.30.0 to 0.30.1. - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.30.0...v0.30.1) --- updated-dependencies: - dependency-name: k8s.io/client-go dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump k8s.io/component-base from 0.28.5 to 0.30.1 (#275) Bumps [k8s.io/component-base](https://github.com/kubernetes/component-base) from 0.28.5 to 0.30.1. - [Commits](https://github.com/kubernetes/component-base/compare/v0.28.5...v0.30.1) --- updated-dependencies: - dependency-name: k8s.io/component-base dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump k8s.io/apiserver from 0.28.5 to 0.30.1 (#274) Bumps [k8s.io/apiserver](https://github.com/kubernetes/apiserver) from 0.28.5 to 0.30.1. - [Commits](https://github.com/kubernetes/apiserver/compare/v0.28.5...v0.30.1) --- updated-dependencies: - dependency-name: k8s.io/apiserver dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix XDG_DATA_HOME build issue (#264) This mirrors the same fix made previously in operator-controller: https://github.com/operator-framework/operator-controller/pull/790 Signed-off-by: Tayler Geiger * Change default namespace to olmv1-system (#283) * :seedling: Bump k8s.io/apiextensions-apiserver from 0.30.0 to 0.30.2 (#284) Bumps [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) from 0.30.0 to 0.30.2. - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.30.0...v0.30.2) --- updated-dependencies: - dependency-name: k8s.io/apiextensions-apiserver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/containerd/containerd from 1.7.16 to 1.7.18 (#282) Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.16 to 1.7.18. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.16...v1.7.18) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix codecov-action params (#287) * `functionalities` param is no longer exist. It was used to enable file fixes to ignore common lines from coverage. This feature is now seems to be on by default. * Adding `disable_search` because we do not need for the codecov action to search for coverage files: we explicitly provide files. Signed-off-by: Mikalai Radchuk * Use url.Scheme to determine port number (#289) Signed-off-by: Todd Short * Fixing the labels for better identify metrics (#292) As the label selector used for both catalogd and operator-controller metrics services is "control-plane: controller-manager". Hence changing the labels in both operator-controller and catalogd to make sure we do not overlap. Refer https://github.com/operator-framework/operator-controller/issues/955 for details Signed-off-by: Lalatendu Mohanty * adding gzip content support (#293) Signed-off-by: Jordan Keister * :seedling: Bump actions/add-to-project from 1.0.1 to 1.0.2 (#291) Bumps [actions/add-to-project](https://github.com/actions/add-to-project) from 1.0.1 to 1.0.2. - [Release notes](https://github.com/actions/add-to-project/releases) - [Commits](https://github.com/actions/add-to-project/compare/v1.0.1...v1.0.2) --- updated-dependencies: - dependency-name: actions/add-to-project dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/prometheus/client_golang (#286) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.18.0 to 1.19.1. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.18.0...v1.19.1) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/google/go-containerregistry (#285) Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.19.1 to 0.19.2. - [Release notes](https://github.com/google/go-containerregistry/releases) - [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml) - [Commits](https://github.com/google/go-containerregistry/compare/v0.19.1...v0.19.2) --- updated-dependencies: - dependency-name: github.com/google/go-containerregistry dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/go-logr/logr from 1.4.1 to 1.4.2 (#279) Bumps [github.com/go-logr/logr](https://github.com/go-logr/logr) from 1.4.1 to 1.4.2. - [Release notes](https://github.com/go-logr/logr/releases) - [Changelog](https://github.com/go-logr/logr/blob/master/CHANGELOG.md) - [Commits](https://github.com/go-logr/logr/compare/v1.4.1...v1.4.2) --- updated-dependencies: - dependency-name: github.com/go-logr/logr dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/onsi/ginkgo/v2 from 2.17.3 to 2.19.0 (#277) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.17.3 to 2.19.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.17.3...v2.19.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/operator-framework/operator-registry (#281) Bumps [github.com/operator-framework/operator-registry](https://github.com/operator-framework/operator-registry) from 1.42.0 to 1.43.1. - [Release notes](https://github.com/operator-framework/operator-registry/releases) - [Commits](https://github.com/operator-framework/operator-registry/compare/v1.42.0...v1.43.1) --- updated-dependencies: - dependency-name: github.com/operator-framework/operator-registry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * check the underlying storage for existing cluster catalog content (#290) Signed-off-by: Igor Troyanovsky * :seedling: Bump github.com/operator-framework/operator-registry (#294) Bumps [github.com/operator-framework/operator-registry](https://github.com/operator-framework/operator-registry) from 1.43.1 to 1.44.0. - [Release notes](https://github.com/operator-framework/operator-registry/releases) - [Commits](https://github.com/operator-framework/operator-registry/compare/v1.43.1...v1.44.0) --- updated-dependencies: - dependency-name: github.com/operator-framework/operator-registry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Share common CA with OLMv1 in overlays/cert-manager (#296) Use kustomization Components to share a common ClusterIssuer with operator-controller. Fixes #295 Signed-off-by: Todd Short * :seedling: Bump github.com/containerd/containerd from 1.7.18 to 1.7.19 (#297) Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.18 to 1.7.19. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.18...v1.7.19) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * reduce cpu requests (#298) Signed-off-by: Jordan Keister * Remove second installation of cert-manager (#300) Signed-off-by: Mikalai Radchuk * Bump ginkgo CLI (#301) Signed-off-by: Mikalai Radchuk * :seedling: Bump github.com/google/go-containerregistry (#302) Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.19.2 to 0.20.0. - [Release notes](https://github.com/google/go-containerregistry/releases) - [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml) - [Commits](https://github.com/google/go-containerregistry/compare/v0.19.2...v0.20.0) --- updated-dependencies: - dependency-name: github.com/google/go-containerregistry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump google.golang.org/grpc from 1.64.0 to 1.64.1 (#303) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.64.0 to 1.64.1. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.64.0...v1.64.1) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * shift gzip lib to active fork (#311) Signed-off-by: Jordan Keister * Move all packages from /pkg to /internal (#310) Ahead of an initial 1.0.0 release, we shouldn't preemptively expose any packages publicly. Instead, let's start my making any packages internal, and we can expose them publicly later on. This commit moves everything currently in /pkg to /internal for now. Signed-off-by: kevinrizza * :seedling: Bump github.com/klauspost/compress from 1.17.8 to 1.17.9 (#312) Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.8 to 1.17.9. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.8...v1.17.9) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/google/go-containerregistry (#315) Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.20.0 to 0.20.1. - [Release notes](https://github.com/google/go-containerregistry/releases) - [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml) - [Commits](https://github.com/google/go-containerregistry/compare/v0.20.0...v0.20.1) --- updated-dependencies: - dependency-name: github.com/google/go-containerregistry dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/operator-framework/operator-registry (#319) Bumps [github.com/operator-framework/operator-registry](https://github.com/operator-framework/operator-registry) from 1.44.0 to 1.45.0. - [Release notes](https://github.com/operator-framework/operator-registry/releases) - [Commits](https://github.com/operator-framework/operator-registry/compare/v1.44.0...v1.45.0) --- updated-dependencies: - dependency-name: github.com/operator-framework/operator-registry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump k8s.io/apiextensions-apiserver from 0.30.2 to 0.30.3 (#320) Bumps [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) from 0.30.2 to 0.30.3. - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.30.2...v0.30.3) --- updated-dependencies: - dependency-name: k8s.io/apiextensions-apiserver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Include OperatorHub.io ClusterCatalog in releases (#321) Also adds optional instructions for adding the OperatorHub.io ClusterCatalog to a cluster. Signed-off-by: Tayler Geiger * ✨ json-lines interface: set content-type, enforce format, document interface (#313) * set content-type for ndjson Signed-off-by: Jordan Keister * generate json-lines validation data Signed-off-by: Jordan Keister * added docs for interface format Signed-off-by: Jordan Keister --------- Signed-off-by: Jordan Keister * :seedling: Bump github.com/containerd/containerd from 1.7.19 to 1.7.20 (#324) Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.19 to 1.7.20. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.19...v1.7.20) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add dependabot K8s dependencies group (#322) Signed-off-by: Mikalai Radchuk * add catalogd upgrade test (#314) Signed-off-by: Ankita Thomas * Add installation script (#325) This follows the release pattern used in operator-controller where an install.sh script is used for a multi-step installation process. The OperatorHub ClusterCatalog is also included in the release artifacts. Also adjusted the Makefile to use the install.sh for deploy. Signed-off-by: Tayler Geiger * Update run-latest-release Makefile target (#326) * 🌱 Revert 2 previous PRs (#327) * Revert "Update run-latest-release Makefile target (#326)" This reverts commit 74de15aa8e50e0764eb7f97c1a667dc41b471a9a. * Revert "Add installation script (#325)" This reverts commit bad488ef1e8245db4e2ca7bb90b6ef7a7a3e4f63. * Add installation script to releases (#328) This follows the release pattern used in operator-controller where an install.sh script is used for a multi-step installation process. The OperatorHub ClusterCatalog is also included in the release artifacts. Also adjusted the Makefile to use the install.sh for deploy. Signed-off-by: Tayler Geiger * Edit Makefile targets to use install.sh (#329) Adjusts several Makefile targets to use the new install.sh script. Includes adjustments to test-upgrade-e2e to use a new target that only installs the catalogd manifest so cert-manager can still be installed first for use in the image registry. Signed-off-by: Tayler Geiger * capturing gzip catalog demo as asciicast (#323) Signed-off-by: Jordan Keister * :seedling: Bump github.com/onsi/gomega from 1.33.1 to 1.34.0 (#332) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.33.1 to 1.34.0. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.33.1...v1.34.0) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/onsi/ginkgo/v2 from 2.19.0 to 2.19.1 (#331) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.19.0 to 2.19.1. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.19.0...v2.19.1) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/onsi/gomega from 1.34.0 to 1.34.1 (#333) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.34.0 to 1.34.1. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.34.0...v1.34.1) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * default-catalogs.yaml: add 10m poll (#335) * ✨ initial api audit type alignment (#330) * initial api audit Signed-off-by: Jordan Keister * review resolutions Signed-off-by: Jordan Keister --------- Signed-off-by: Jordan Keister * :seedling: Bump github.com/onsi/ginkgo/v2 from 2.19.1 to 2.20.0 (#338) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.19.1 to 2.20.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.19.1...v2.20.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/google/go-containerregistry (#337) Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.20.1 to 0.20.2. - [Release notes](https://github.com/google/go-containerregistry/releases) - [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml) - [Commits](https://github.com/google/go-containerregistry/compare/v0.20.1...v0.20.2) --- updated-dependencies: - dependency-name: github.com/google/go-containerregistry dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/prometheus/client_golang (#344) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.19.1 to 1.20.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/v1.20.0/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.19.1...v1.20.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump the k8s-dependencies group with 6 updates (#343) * :seedling: Bump the k8s-dependencies group with 6 updates Bumps the k8s-dependencies group with 6 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.30.3` | `0.31.0` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.30.3` | `0.31.0` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.30.3` | `0.31.0` | | [k8s.io/apiserver](https://github.com/kubernetes/apiserver) | `0.30.3` | `0.31.0` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.30.3` | `0.31.0` | | [k8s.io/component-base](https://github.com/kubernetes/component-base) | `0.30.3` | `0.31.0` | Updates `k8s.io/api` from 0.30.3 to 0.31.0 - [Commits](https://github.com/kubernetes/api/compare/v0.30.3...v0.31.0) Updates `k8s.io/apiextensions-apiserver` from 0.30.3 to 0.31.0 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.30.3...v0.31.0) Updates `k8s.io/apimachinery` from 0.30.3 to 0.31.0 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.30.3...v0.31.0) Updates `k8s.io/apiserver` from 0.30.3 to 0.31.0 - [Commits](https://github.com/kubernetes/apiserver/compare/v0.30.3...v0.31.0) Updates `k8s.io/client-go` from 0.30.3 to 0.31.0 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.30.3...v0.31.0) Updates `k8s.io/component-base` from 0.30.3 to 0.31.0 - [Commits](https://github.com/kubernetes/component-base/compare/v0.30.3...v0.31.0) --- updated-dependencies: - dependency-name: k8s.io/api dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-dependencies - dependency-name: k8s.io/apiextensions-apiserver dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-dependencies - dependency-name: k8s.io/apimachinery dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-dependencies - dependency-name: k8s.io/apiserver dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-dependencies - dependency-name: k8s.io/client-go dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-dependencies - dependency-name: k8s.io/component-base dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-dependencies ... Signed-off-by: dependabot[bot] * Bump controller-runtime from 0.18.4 to 0.19.0 Signed-off-by: Per Goncalves da Silva --------- Signed-off-by: dependabot[bot] Signed-off-by: Per Goncalves da Silva Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Per Goncalves da Silva * :seedling: change GVK to use olm.operatorframework.io (#342) Signed-off-by: Jordan Keister * Removing the catalogd from app.kubernetes.io/name (#347) As this namespace is shared between catalogd operator-framework-catalogd Fixes issue #346 Signed-off-by: Lalatendu Mohanty * :seedling: Bump github.com/operator-framework/operator-registry from 1.45.0 to 1.46.0 (#345) * :seedling: Bump github.com/operator-framework/operator-registry Bumps [github.com/operator-framework/operator-registry](https://github.com/operator-framework/operator-registry) from 1.45.0 to 1.46.0. - [Release notes](https://github.com/operator-framework/operator-registry/releases) - [Commits](https://github.com/operator-framework/operator-registry/compare/v1.45.0...v1.46.0) --- updated-dependencies: - dependency-name: github.com/operator-framework/operator-registry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * bump controller-gen to v0.16.1 Signed-off-by: Per Goncalves da Silva --------- Signed-off-by: dependabot[bot] Signed-off-by: Per Goncalves da Silva Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Per Goncalves da Silva * ✨ Capture catalog content timestamp in ClusterCatalogStatus (#334) * Capture catalog content timestamp in ClusterCatalogStatus Signed-off-by: Rashmi Gottipati * address reviews (partial) Signed-off-by: Rashmi Gottipati * address review feedback Signed-off-by: Rashmi Gottipati * Address review comments Signed-off-by: Rashmi Gottipati --------- Signed-off-by: Rashmi Gottipati * :seedling: Bump github.com/onsi/ginkgo/v2 from 2.20.0 to 2.20.1 (#350) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.20.0 to 2.20.1. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.20.0...v2.20.1) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/prometheus/client_golang (#351) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.20.0 to 1.20.2. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.20.0...v1.20.2) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/containerd/containerd from 1.7.20 to 1.7.21 (#352) Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.20 to 1.7.21. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.20...v1.7.21) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Catalog Priority (#353) Adds an int32 field to allow users to optionally set priority of catalogs. This priority value may be taken into account during bundle selection from multiple catalogs to remove ambiguity. Signed-off-by: dtfranz * add v1.0 and v1.x issues to OLMv1 project automatically (#354) Signed-off-by: Joe Lanford * :seedling: Bump bingo + tools (#358) * Add bingo-upgrade target to Makefile Signed-off-by: Per Goncalves da Silva * Upgrade bingo tools Signed-off-by: Per Goncalves da Silva * Regenerate manifests Signed-off-by: Per Goncalves da Silva --------- Signed-off-by: Per Goncalves da Silva Co-authored-by: Per Goncalves da Silva * bugfix: fix printcolumn for lastUnpacked based on json tag and not field name (#361) Signed-off-by: Rashmi Gottipati * :seedling: Bump github.com/onsi/ginkgo/v2 from 2.20.1 to 2.20.2 (#360) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.20.1 to 2.20.2. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.20.1...v2.20.2) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/onsi/gomega from 1.34.1 to 1.34.2 (#359) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.34.1 to 1.34.2. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.34.1...v1.34.2) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update cert-manager to v1.15.3 (#367) Signed-off-by: Todd Short * Remove status.phase field from the code and doc references (#368) Signed-off-by: Todd Short * 🌱 Add webhook to add a name label to ClusterCatalogs (#356) * Add webhook to name label ClusterCatalogs * Linter fixups * Added bit more webhook test coverage * Use catalogd version & clean up TLS args Signed-off-by: Brett Tofel * Fix label name Signed-off-by: Brett Tofel * From stand-alone webhook to operator internal Signed-off-by: Brett Tofel * Think this fixes e2e-upgrade not sure why PR changes might necessitate this, but it seems legit to delete deployment first Signed-off-by: Brett Tofel * PR review changes so far... - get MutaingWebhookConfig from kubebuilder; - stop deleting deployment on only-deploy; - use the existing matchLabel, stop adding webhook label to operator; - rename the name label to metadata.name (but not in API yet). Signed-off-by: Brett Tofel * Restore CA issuer config Signed-off-by: Brett Tofel * Fix unit tests Signed-off-by: Brett Tofel * Addresses review comments around TLS cert config Signed-off-by: Brett Tofel * Move RBAC for webhook to kb directive Signed-off-by: Brett Tofel * Move allow-direct-injection to secretTemplate Signed-off-by: Brett Tofel * Make metadata.name an API constant Signed-off-by: Brett Tofel * Use MetaDataNameLabel API constant in log line Signed-off-by: Brett Tofel * Combine cert watchers Signed-off-by: Brett Tofel * Move cert watching back to ctr-rt manager Signed-off-by: Brett Tofel * Address review comments Signed-off-by: Brett Tofel * Address review comments 2 Signed-off-by: Brett Tofel --------- Signed-off-by: Brett Tofel * Move cert-manager.io patch into tls component (#372) Signed-off-by: Todd Short * :seedling: Bump github.com/prometheus/client_golang (#375) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.20.2 to 1.20.3. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/v1.20.3/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.20.2...v1.20.3) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add label creation checking in the e2e (#374) Signed-off-by: Todd Short * Add matchCondition to webhook config (#376) Should add some efficiency as it only lets the webhook fire when needed Signed-off-by: Brett Tofel * Fix matchConditions to be compatible with GenerateName (#382) Signed-off-by: Todd Short * Force a rename of the catalogd certificate (#386) This will cause the catalogd deployment to restart, meaning that the catalogd will update quicker (rather than waiting on k8s to update the certificates via the volume) Signed-off-by: Todd Short * :seedling: Bump github.com/operator-framework/operator-registry (#387) Bumps [github.com/operator-framework/operator-registry](https://github.com/operator-framework/operator-registry) from 1.46.0 to 1.47.0. - [Release notes](https://github.com/operator-framework/operator-registry/releases) - [Commits](https://github.com/operator-framework/operator-registry/compare/v1.46.0...v1.47.0) --- updated-dependencies: - dependency-name: github.com/operator-framework/operator-registry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * 📖 [Docs] Document tilt-support install (#388) * Document tilt-support install Signed-off-by: Brett Tofel * Improve tilt-support text Signed-off-by: Brett Tofel --------- Signed-off-by: Brett Tofel * :seedling: Bump github.com/containerd/containerd from 1.7.21 to 1.7.22 (#391) Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.21 to 1.7.22. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.21...v1.7.22) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ✨ Ensure docker registry CA is trusted in e2e tests (#377) * Ensure docker registry CA is trusted in e2e tests * Restructure based on feedback * Fix FS cache for image refs with tags (#394) Signed-off-by: Mikalai Radchuk * Fixes name of httputil test file (#395) Signed-off-by: Per Goncalves da Silva Co-authored-by: Per Goncalves da Silva * Add .idea to .gitignore (#393) Signed-off-by: Per Goncalves da Silva Co-authored-by: Per Goncalves da Silva * Remove TLSVerify/PullSecret fields (#369) Remove fields that will not have long term support committed to them to prepare for the v1.0 release. Removed Fields: - spec.source.image.insecureSkipTLSVerify - spec.source.image.pullSecret GH Issue Ref: #355 Signed-off-by: Per Goncalves da Silva * Avoid a network call for digest based images (#396) Signed-off-by: Mikalai Radchuk * :seedling: Bump the k8s-dependencies group with 6 updates (#398) Bumps the k8s-dependencies group with 6 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.31.0` | `0.31.1` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.31.0` | `0.31.1` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.31.0` | `0.31.1` | | [k8s.io/apiserver](https://github.com/kubernetes/apiserver) | `0.31.0` | `0.31.1` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.31.0` | `0.31.1` | | [k8s.io/component-base](https://github.com/kubernetes/component-base) | `0.31.0` | `0.31.1` | Updates `k8s.io/api` from 0.31.0 to 0.31.1 - [Commits](https://github.com/kubernetes/api/compare/v0.31.0...v0.31.1) Updates `k8s.io/apiextensions-apiserver` from 0.31.0 to 0.31.1 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.31.0...v0.31.1) Updates `k8s.io/apimachinery` from 0.31.0 to 0.31.1 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.31.0...v0.31.1) Updates `k8s.io/apiserver` from 0.31.0 to 0.31.1 - [Commits](https://github.com/kubernetes/apiserver/compare/v0.31.0...v0.31.1) Updates `k8s.io/client-go` from 0.31.0 to 0.31.1 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.31.0...v0.31.1) Updates `k8s.io/component-base` from 0.31.0 to 0.31.1 - [Commits](https://github.com/kubernetes/component-base/compare/v0.31.0...v0.31.1) --- updated-dependencies: - dependency-name: k8s.io/api dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apiextensions-apiserver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apimachinery dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apiserver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/client-go dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/component-base dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix unnecessary lastUnpacked status updates (#397) We should not be updating lastUnpacked status fields when we read from the cache Signed-off-by: Mikalai Radchuk * ✨ unpacker: switch from google/go-containerregistry to containers/image (#399) * copy containers_image.go from operator-controller Signed-off-by: Joe Lanford * initial modifications for naming and types Signed-off-by: Joe Lanford * unpacker: switch to containers/image-based implementation Signed-off-by: Joe Lanford --------- Signed-off-by: Joe Lanford * :seedling: Align ClusterCatalog API godoc with OpenShift API conventions (#390) * Update godoc strings for ClusterCatalog API Signed-off-by: Per Goncalves da Silva * Regenerate manifests Signed-off-by: Per Goncalves da Silva * Apply suggestions from code review Text fixes Co-authored-by: Bryce Palmer * Address reviewer comments Signed-off-by: Per Goncalves da Silva * Update api/core/v1alpha1/clustercatalog_types.go Co-authored-by: Bryce Palmer * Apply suggestions from code review Co-authored-by: Joe Lanford Signed-off-by: Per Goncalves da Silva --------- Signed-off-by: Per Goncalves da Silva Co-authored-by: Per Goncalves da Silva Co-authored-by: Bryce Palmer Co-authored-by: Joe Lanford * Add CI to check if golang version updated (#401) Signed-off-by: Todd Short * Combine the catalogd services (#402) Only need to define one service for: * metrics * webhook * catalogd itself Clean up the name of the service (now `catalogd-service`) and any corresponding resources Renumber the ports to 7443/8443/9443. The external port for the catalog server is either 80 or 443. Signed-off-by: Todd Short * Update documentation and default to new service name. (#406) Signed-off-by: Todd Short * fix: make post-upgrade-e2e checks wait for ClusterCatalog to be reconciled (#407) Signed-off-by: Joe Lanford * fix: unpack cache cleanup should ignore missing files (#404) Signed-off-by: Joe Lanford * use controller-runtime Terminal error instead of custom Unrecoverable error (#405) Signed-off-by: Joe Lanford * Refer to the correct location for go-verdiff (#408) The location is different than the operator-controller repo. Signed-off-by: Todd Short * :seedling: Bump github.com/prometheus/client_golang (#403) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.20.3 to 1.20.4. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.20.3...v1.20.4) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * 🐛 Handle finalizers (creation and deletion) better (#411) * 🐛 Handle finalizers (creation and deletion) better Closes [409](https://github.com/operator-framework/catalogd/issues/409) * Move the finalizer setup Move the finalizer setup out from main.go, and into the controller code. This allows the finalizers to be initialized and used in the test code. Signed-off-by: Todd Short * Undo rename of fbcDeletionFinalizer Signed-off-by: Todd Short --------- Signed-off-by: Todd Short Co-authored-by: Todd Short * ⚠ Status condition clean up (#379) * ⚠ Status condition clean up [RFC: ClusterCatalog Status Conditions](https://docs.google.com/document/d/1Kg8ovX8d25OqGa5utwcKbX3nN3obBl2KIYJHYz6IlKU/edit) implementation. Closes [363](operator-framework#363) Closes [364](operator-framework#364) Closes [365](operator-framework#365) Co-authored-by: Ankita Thomas Co-authored-by: Anik Bhattacharjee * Handle new finalizer code Signed-off-by: Todd Short * Set StatusUpdated to true for finalizers Signed-off-by: Todd Short --------- Signed-off-by: Todd Short Co-authored-by: Ankita Thomas Co-authored-by: Todd Short * Fix wait in pre-upgrade-setup test (#415) Signed-off-by: Per Goncalves da Silva Co-authored-by: Per Goncalves da Silva * :seedling: Bump github.com/klauspost/compress from 1.17.9 to 1.17.10 (#413) Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.9 to 1.17.10. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.9...v1.17.10) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⚠ Update the Progressing Status condition `Terminal` reason to `Blocked` (#414) Closes [412](https://github.com/operator-framework/catalogd/issues/412) * ✨ Use default creds if present for pulling catalog images (#416) * main.go: improve logging for configuration of global auth (#417) Signed-off-by: Joe Lanford * main.go: clarify auth file access error message (#418) Signed-off-by: Joe Lanford * main.go: switch to klog-based logger (#419) Signed-off-by: Joe Lanford * ⚠️ types tightening (#384) * types tightening * switch to status.lastUnpacked for sole unpacked timestamp, use CEL validation for spec.source and status.resolvedSource Signed-off-by: Ankita Thomas * rename unpacker result's lastTransitionTime to unpackTime, set observedGeneration in conditions * restructure validation checks to only check for image source type Signed-off-by: Ankita Thomas * fail on missing validator in types test Signed-off-by: Ankita Thomas * don't skip bad image refs when testing for needsUnpack allow bad image refs to pass through to unpacker to propagate error to Progressing status Signed-off-by: Ankita Thomas * compare catalog generation and condition ObservedGeneration for needsUnpack Signed-off-by: Ankita Thomas --------- Signed-off-by: Ankita Thomas Co-authored-by: Ankita Thomas * :sparkles: update GoDoc comments to be accurate with latest api changes (#423) * update GoDoc comments to be accurate with latest api changes Signed-off-by: everettraven * formatting Signed-off-by: everettraven * make verify Signed-off-by: everettraven * minor grammar fix Co-authored-by: Jordan Keister * regen crds Signed-off-by: everettraven --------- Signed-off-by: everettraven Co-authored-by: Jordan Keister * clustercatalog_controller: hacky, but more correct status updating in reconciler (#424) Signed-off-by: Joe Lanford * ✨ Add PullSecret controller to save pull secret data locally (#425) * ✨ Add PullSecret controller to save pull secret data locally RFC: https://docs.google.com/document/d/1BXD6kj5zXHcGiqvJOikU2xs8kV26TPnzEKp6n7TKD4M/edit#heading=h.x3tfh25grvnv * main.go: improved cache configuration for watching pull secret Signed-off-by: Joe Lanford --------- Signed-off-by: Joe Lanford * Align catalog service name in documentation (#428) * :seedling: Bump github.com/klauspost/compress from 1.17.10 to 1.17.11 (#430) Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.10 to 1.17.11. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.10...v1.17.11) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix pulling signed images (#431) This fixes "pushing signatures for OCI images is not supported" error when working with signed source images. If policy context requires signature validation for a registry we will still be performing it on pull, but we will be removing source signatures when copying into a temporary OCI layout for unpacking. Signed-off-by: Mikalai Radchuk * :seedling: Bump github.com/prometheus/client_golang (#433) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.20.4 to 1.20.5. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.20.4...v1.20.5) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/containerd/containerd from 1.7.22 to 1.7.23 (#434) Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.22 to 1.7.23. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.22...v1.7.23) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Address goreleaser deprecated flags (#435) Signed-off-by: Per Goncalves da Silva Co-authored-by: Per Goncalves da Silva * :sparkles: Adding Availability enum to catalog spec (#421) * [WIP] Adding Availability enum to catalog spec Signed-off-by: Lalatendu Mohanty * Removing the finalizer after the catalog is disabled Signed-off-by: Lalatendu Mohanty * Adding unit tests Signed-off-by: Lalatendu Mohanty --------- Signed-off-by: Lalatendu Mohanty * ⚠️ change catalog-specific URL from full path to API endpoint ref (#429) * change catalog-specific URL from full path to API endpoint ref solves #427 and implements phase 1 of the CatalogD expandable interface. This phase just moves from `status.contentURL` to `status.baseURL`, and will be used to provide reference to the catalog-specific API instead of the full path to JSONLines-formatted content, plus tests and documentation. Signed-off-by: Jordan Keister * sticking to catalog-centric reference, and updated type Signed-off-by: Jordan Keister * remove some magic numbers Signed-off-by: Jordan Keister * review reconciliation Signed-off-by: Jordan Keister --------- Signed-off-by: Jordan Keister * use spec's ref instead of canonical ref when copying catalog image (#438) When used in conjuction with a "tag-only" registries.conf mirror registry configuration, our containers/image unpacker fails. This is because we resolve a canonical ref from the tag, and then use the digest-based reference to actually copy the image, thus thwarting the tag-only configuration. This commit ensures that we always copy the image using the reference provided in the spec. Signed-off-by: Joe Lanford * fix a missed e2e testdata path update (#440) Signed-off-by: Jordan Keister * adding additional waits to prevent e2e cert-manager failures (#441) Signed-off-by: Jordan Keister * use Go version from go.mod (#442) Signed-off-by: Joe Lanford * demo was not updated to work with the cert-manager changes made earlier. (#439) In addition, there are some new waits introduced to give some more signal around some (very) intermittent install failures from the install script. This script now completely eschews installation via locally-defined resources and relies entirely on the latest release's scripts/manifests to install on the local cluster, so that we have fewer scripts to maintain. Signed-off-by: Jordan Keister * :seedling: Bump the k8s-dependencies group with 6 updates (#445) Bumps the k8s-dependencies group with 6 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.31.1` | `0.31.2` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.31.1` | `0.31.2` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.31.1` | `0.31.2` | | [k8s.io/apiserver](https://github.com/kubernetes/apiserver) | `0.31.1` | `0.31.2` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.31.1` | `0.31.2` | | [k8s.io/component-base](https://github.com/kubernetes/component-base) | `0.31.1` | `0.31.2` | Updates `k8s.io/api` from 0.31.1 to 0.31.2 - [Commits](https://github.com/kubernetes/api/compare/v0.31.1...v0.31.2) Updates `k8s.io/apiextensions-apiserver` from 0.31.1 to 0.31.2 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.31.1...v0.31.2) Updates `k8s.io/apimachinery` from 0.31.1 to 0.31.2 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.31.1...v0.31.2) Updates `k8s.io/apiserver` from 0.31.1 to 0.31.2 - [Commits](https://github.com/kubernetes/apiserver/compare/v0.31.1...v0.31.2) Updates `k8s.io/client-go` from 0.31.1 to 0.31.2 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.31.1...v0.31.2) Updates `k8s.io/component-base` from 0.31.1 to 0.31.2 - [Commits](https://github.com/kubernetes/component-base/compare/v0.31.1...v0.31.2) --- updated-dependencies: - dependency-name: k8s.io/api dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apiextensions-apiserver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apimachinery dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apiserver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/client-go dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/component-base dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/operator-framework/operator-registry (#446) Bumps [github.com/operator-framework/operator-registry](https://github.com/operator-framework/operator-registry) from 1.47.0 to 1.48.0. - [Release notes](https://github.com/operator-framework/operator-registry/releases) - [Commits](https://github.com/operator-framework/operator-registry/compare/v1.47.0...v1.48.0) --- updated-dependencies: - dependency-name: github.com/operator-framework/operator-registry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * add a demo-update generation workflow step to let us know when we have broken demo generation (#444) Signed-off-by: Jordan Keister * :seedling: Bump github.com/onsi/gomega from 1.34.2 to 1.35.1 (#450) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.34.2 to 1.35.1. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.34.2...v1.35.1) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/onsi/ginkgo/v2 from 2.20.2 to 2.21.0 (#449) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.20.2 to 2.21.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.20.2...v2.21.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * API updates based on external review (#443) Signed-off-by: everettraven Signed-off-by: Mikalai Radchuk * :warning: Bump ClusterCatalog API to v1 (#380) * bump ClusterCatalog API to v1 Signed-off-by: Per Goncalves da Silva * Update test/e2e/unpack_test.go --------- Signed-off-by: Per Goncalves da Silva Co-authored-by: Per Goncalves da Silva Co-authored-by: Joe Lanford * this fixes two issues made manifest in testing the upgrade-e2e case subsequent to cutting the new RC. (#457) 1. [here](https://github.com/operator-framework/catalogd/commit/2f96c573d5a8e5197c53f8219f1e32a24d8d4b8a#diff-b104edd120983248771684630cd3f66af28359c829df801a5eea77845d459aa0R33) an accidental label change in the v1 api promotion 2. [here](https://github.com/operator-framework/catalogd/commit/2f96c573d5a8e5197c53f8219f1e32a24d8d4b8a#diff-b104edd120983248771684630cd3f66af28359c829df801a5eea77845d459aa0R69) a location which I failed to update for the new Progressing==True logic for happy path clustercatalog unpacking. This was masked due to the fact that we knew we were making breaking changes, and the upgrade-e2e test will fail until we have cut a new release. 😞 Signed-off-by: Jordan Keister * 🐛 Check cluster is running for non-standalone Make targets (#437) * Check Kind running for non-standalong Make targets Signed-off-by: Brett Tofel * improve test-e2e comment Co-authored-by: Jordan Keister * improve install comment Co-authored-by: Jordan Keister * Change to generic check for cluster Signed-off-by: Brett Tofel * Error on non-running cluster suggests what to do Signed-off-by: Brett Tofel --------- Signed-off-by: Brett Tofel Co-authored-by: Jordan Keister * Update go version checker (#458) * Handle new files (old version is empty) * Handle the case where .0 patch is added/removed Signed-off-by: Todd Short * bump ginkgo bingo dependency to 2.21.0 (#456) Signed-off-by: Jordan Keister * :seedling: Bump codecov/codecov-action from 4 to 5 (#459) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4...v5) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * doc: add steps to build and deploy locally to contributing guide (#463) - Updated the Contributing guide with detailed instructions for building and deploying the project locally. - Steps include creating a local kind cluster, building the container, and loading it into the cluster. This addition helps contributors set up their local environment efficiently. * fix: update kind-load target to ensure that works aligned with controller-operator (#462) Standardizing this method simplifies workflows and makes the project more contributor-friendly * feat: add support for Podman as a container runtime (#464) Since docker requires a license in some scenarios, we might have contributors who prefer to use Podman. This commit introduces the changes necessary to support both. * Fix check-cluster logic (#466) Signed-off-by: Brett Tofel * enable go-apidiff in merge queue (#470) Signed-off-by: Joe Lanford * Remove check-cluster dependency from test-e2e (#473) `check-cluster` is already a dependency of the `install` targt, which is a dependency of `e2e`. It does not need to be a dependency of `test-e2e` which _just_ runs the tests without any setup. Signed-off-by: Todd Short * :seedling: Bump the k8s-dependencies group with 6 updates (#467) Bumps the k8s-dependencies group with 6 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.31.2` | `0.31.3` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.31.2` | `0.31.3` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.31.2` | `0.31.3` | | [k8s.io/apiserver](https://github.com/kubernetes/apiserver) | `0.31.2` | `0.31.3` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.31.2` | `0.31.3` | | [k8s.io/component-base](https://github.com/kubernetes/component-base) | `0.31.2` | `0.31.3` | Updates `k8s.io/api` from 0.31.2 to 0.31.3 - [Commits](https://github.com/kubernetes/api/compare/v0.31.2...v0.31.3) Updates `k8s.io/apiextensions-apiserver` from 0.31.2 to 0.31.3 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.31.2...v0.31.3) Updates `k8s.io/apimachinery` from 0.31.2 to 0.31.3 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.31.2...v0.31.3) Updates `k8s.io/apiserver` from 0.31.2 to 0.31.3 - [Commits](https://github.com/kubernetes/apiserver/compare/v0.31.2...v0.31.3) Updates `k8s.io/client-go` from 0.31.2 to 0.31.3 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.31.2...v0.31.3) Updates `k8s.io/component-base` from 0.31.2 to 0.31.3 - [Commits](https://github.com/kubernetes/component-base/compare/v0.31.2...v0.31.3) --- updated-dependencies: - dependency-name: k8s.io/api dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apiextensions-apiserver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apimachinery dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apiserver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/client-go dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/component-base dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/onsi/ginkgo/v2 from 2.21.0 to 2.22.0 (#468) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.21.0 to 2.22.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.21.0...v2.22.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/containerd/containerd from 1.7.23 to 1.7.24 (#469) Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.23 to 1.7.24. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.23...v1.7.24) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/onsi/gomega from 1.35.1 to 1.36.0 (#472) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.35.1 to 1.36.0. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.35.1...v1.36.0) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump github.com/stretchr/testify from 1.9.0 to 1.10.0 (#475) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.9.0 to 1.10.0. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: add verify-crd-compatibility make target and GHA (#471) * (ci): add verify-crd-compatibility make target and GHA using the crd-diff tool with the same configuration as recently merged into operator-controller Signed-off-by: everettraven * improve local developer experience Signed-off-by: everettraven --------- Signed-off-by: everettraven * :seedling: Bump github.com/onsi/gomega from 1.36.0 to 1.36.1 (#477) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.36.0 to 1.36.1. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.36.0...v1.36.1) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump the k8s-dependencies group with 6 updates (#479) Bumps the k8s-dependencies group with 6 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.31.3` | `0.31.4` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.31.3` | `0.31.4` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.31.3` | `0.31.4` | | [k8s.io/apiserver](https://github.com/kubernetes/apiserver) | `0.31.3` | `0.31.4` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.31.3` | `0.31.4` | | [k8s.io/component-base](https://github.com/kubernetes/component-base) | `0.31.3` | `0.31.4` | Updates `k8s.io/api` from 0.31.3 to 0.31.4 - [Commits](https://github.com/kubernetes/api/compare/v0.31.3...v0.31.4) Updates `k8s.io/apiextensions-apiserver` from 0.31.3 to 0.31.4 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.31.3...v0.31.4) Updates `k8s.io/apimachinery` from 0.31.3 to 0.31.4 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.31.3...v0.31.4) Updates `k8s.io/apiserver` from 0.31.3 to 0.31.4 - [Commits](https://github.com/kubernetes/apiserver/compare/v0.31.3...v0.31.4) Updates `k8s.io/client-go` from 0.31.3 to 0.31.4 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.31.3...v0.31.4) Updates `k8s.io/component-base` from 0.31.3 to 0.31.4 - [Commits](https://github.com/kubernetes/component-base/compare/v0.31.3...v0.31.4) --- updated-dependencies: - dependency-name: k8s.io/api dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apiextensions-apiserver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apimachinery dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apiserver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/client-go dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/component-base dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * :seedling: Bump golang.org/x/crypto from 0.28.0 to 0.31.0 (#480) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.28.0 to 0.31.0. - [Commits](https://github.com/golang/crypto/compare/v0.28.0...v0.31.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * gha: release: only push images for main branch (#481) Signed-off-by: Joe Lanford * e2e: add tests to verify metrics endpoint (#483) * Add check for client in e2e (#485) Depending on how the e2e is run, we may not have a k8s client available. Signed-off-by: Todd Short * Update bingo's ginkgo to v2.22.0 (#486) dependabot updated go.mod, but didn't know about bingo Signed-off-by: Todd Short * Disable HTTP/2 by Default for Webhooks to Mitigate CVE Risks (#484) Ensure HTTP/2 is disabled by default for webhooks. Disabling HTTP/2 mitigates vulnerabilities associated with: - HTTP/2 Stream Cancellation (GHSA-qppj-fm5r-hxr3) - HTTP/2 Rapid Reset (GHSA-4374-p667-p6c8) While CVE fixes exist, they remain insufficient; disabling HTTP/2 helps reduce risks. For details, see: https://github.com/kubernetes/kubernetes/issues/121197 * :nit: remove log saying that http is disabled (#492) * Add check in test-e2e testing to ensure there's a cluster (#474) Signed-off-by: Todd Short * Replace kube-rbac-proxy with controller-runtime metrics authentication/authorization (#460) This commit removes the use of the kube-rbac-proxy image and replaces it with metrics authentication/authorization provided by controller-runtime. The kube-rbac-proxy image is deprecated and will no longer be maintained, which introduces risks to production environments. For more details, see: kubernetes-sigs/kubebuilder#3907 * Updating the ClusterCatalog example (#496) Adding Availability mode to the example output and removing the PollInterval because it is an optional field and now it is called PollIntervalMinutes Signed-off-by: Lalatendu Mohanty * test/e2e/metrics_endpoint_test.go: discover catalogd namespace and improve logging (#503) Signed-off-by: Joe Lanford * :seedling: Bump github.com/onsi/ginkgo/v2 from 2.22.0 to 2.22.2 (#499) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.22.0 to 2.22.2. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.22.0...v2.22.2) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Upgrade github.com/joelanford/ignore from v0.1.0 to v0.1.1 (#501) * Upgrade golang.org/x/net (#502) go: upgraded golang.org/x/crypto v0.31.0 => v0.32.0 go: upgraded golang.org/x/net v0.30.0 => v0.34.0 go: upgraded golang.org/x/sys v0.28.0 => v0.29.0 go: upgraded golang.org/x/term v0.27.0 => v0.28.0 * Monorepo prep commit Signed-off-by: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> * Update catalogd API v1 imports Signed-off-by: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> * Remove redundant catalogd import Signed-off-by: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> * Check in generated manifest files Signed-off-by: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> * [Monorepo] Remove Temporary Makefile Artifacts created by the script - Removed temporary files (`Makefile.orig` and `Makefile.rej`) generated by scripts. - These files are not required and are cleaned up to maintain a tidy repository. * [Monorepo] Update API docs generation to use catalogd from source Updated the target crd-ref-docs for generating CRD reference documentation to use catalogd directly from the source code, replacing the dependency on the outdated repository(https://github.com/operator-framework/catalogd). * [Monorepo] Unify Install Script and YAML File - Consolidated YAML for both projects into operator-controller.yaml. - Updated the install script to utilize the unified YAML file. Co-authored-by: Joe Lanford * [Monorepo] Move catalogd GitHub Actions to Root Workflow and Remove Duplicates - Relocated catalogd-specific GitHub actions to the root `.github/workflows` directory. - Integrated actions to perform catalogd-specific checks at the monorepo level for consistency and centralized management. - Removed duplicate GitHub actions already present in the operator-controller, ensuring no redundancy. - Deleted the following obsolete files from the catalogd directory: - `.github/dependabot.yml` - `.github/pull_request_template.md` - `.github/workflows/add-to-project.yaml` - `.github/workflows/go-apidiff.yaml` - `.github/workflows/go-verdiff.yaml` - `.github/workflows/pr-title.yaml` - `.github/workflows/release.yaml` * [Monorepo] Change target verify-crd-compatibility to skip when CRD does not exist - Resolved failure in the catalogd-crd-diff CI check caused by missing CRDs in the new repository. - Improved the CI and Makefile target to gracefully skip execution when the original CRD does not exist. Note: This is a temporary solution, and we may need to revisit and refine this check in the future. * [Monorepo] Unify Makefile for Lint, Fix Lint Issues, and Correct Imports - Unified linting configuration for both projects, now defined in the root directory. - Addressed Catalogd test file linting issues: - Replaced `assert.Nil(t, err)` with `require.NoError(t, err)` where applicable. - Replaced `assert.NotNil(t, err)` with `require.Error(t, err)` where appropriate. - Fixed import sorting ensuring all files have properly organized imports for the lint does not fail with the issue (File is not -ed). Note this was caused by the replace `catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1"` with `catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1"` * [Monorepo] Unify Release Process - Consolidated the release process to use `operator-controller.yaml` for all requirements. - Removed `catalogd.yaml` as it is no longer necessary. - Simplified the release action: - A single release action now generates images and binaries for both projects. - Unified process ensures consistent release management across the monorepo. * [Monorepo] Combine Unit Tests - Updated the root `Makefile` with a unified `test-unit` target to execute unit tests for the entire project. - Removed the `test-unit` target from the `Makefile` under the `catalogd` directory as it is no longer needed. * [Monorepo] Fix and Unify Tilt Workflow - Added `.tilt-support` directory at the root, updated to work with both `operator-controller` and `catalogd`. - Removed the Tilt workflow from the `catalogd` directory, consolidating all configurations into the root Tilt setup. - Updated configurations to use `catalogd` from the source code instead of fetching it from `github.com/operator-framework/catalogd`. Co-authored-by: Joe Lanford * [Monorepo] Cleanup Redundant Files and Scripts - Removed `check-go-version.sh` from `catalogd/hack/scripts` as it is no longer needed. - Both projects now rely on the `go.mod` file at the root directory for Go version checks. - Removed duplicated files from the repository: - `CODEOWNERS` - `CONTRIBUTING.md` - `DOC` - `LICENSE.md` - Use hack/boilerplate.go.txt from root and remove duplication * [Monorepo] Unify Bingo Usage - Standardized Bingo definitions across `catalogd` and `operator-controller`. - Ensured both projects use the same Bingo config to maintain consistency --------- Signed-off-by: Mikalai Radchuk Signed-off-by: Andy Goldstein Signed-off-by: Rashmi Gottipati Signed-off-by: Joe Lanford Signed-off-by: Anik Signed-off-by: Jordan Keister Signed-off-by: Bryce Palmer Signed-off-by: Bryce Palmer Signed-off-by: Catherine Chan-Tse Signed-off-by: kevinrizza Signed-off-by: Anik Bhattacharjee Signed-off-by: dependabot[bot] Signed-off-by: everettraven Signed-off-by: Tayler Geiger Signed-off-by: Todd Short Signed-off-by: Lalatendu Mohanty Signed-off-by: Igor Troyanovsky Signed-off-by: Ankita Thomas Signed-off-by: Per Goncalves da Silva Signed-off-by: dtfranz Signed-off-by: Brett Tofel Signed-off-by: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> Co-authored-by: Mikalai Radchuk Co-authored-by: Andy Goldstein Co-authored-by: Joe Lanford Co-authored-by: Rashmi Gottipati Co-authored-by: Anik Bhattacharjee Co-authored-by: Jordan Keister Co-authored-by: Bryce Palmer Co-authored-by: oceanc80 Co-authored-by: Kevin Rizza Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mikalai Radchuk <509198+m1kola@users.noreply.github.com> Co-authored-by: Tayler Geiger Co-authored-by: everettraven Co-authored-by: Todd Short Co-authored-by: Lalatendu Mohanty Co-authored-by: Igor Troyanovsky Co-authored-by: Ankita Thomas Co-authored-by: Per Goncalves da Silva Co-authored-by: Daniel Franz Co-authored-by: Per Goncalves da Silva Co-authored-by: Brett Tofel Co-authored-by: Nico Schieder Co-authored-by: Nico Schieder Co-authored-by: Todd Short Co-authored-by: Ankita Thomas --- .github/workflows/catalogd-crd-diff.yaml | 19 + .github/workflows/catalogd-demo.yaml | 25 + .github/workflows/catalogd-e2e.yaml | 31 + .github/workflows/tilt.yaml | 16 +- .goreleaser.yml | 79 +- .idea/.gitignore | 8 + .idea/catalogd.iml | 9 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .tilt-support | 151 +++ Dockerfile | 8 +- Makefile | 58 +- Tiltfile | 31 +- catalogd/.dockerignore | 8 + catalogd/.gitignore | 21 + catalogd/Dockerfile | 8 + catalogd/Makefile | 229 ++++ catalogd/README.md | 169 +++ catalogd/api/doc.go | 22 + catalogd/api/v1/clustercatalog_types.go | 357 ++++++ catalogd/api/v1/clustercatalog_types_test.go | 452 +++++++ catalogd/api/v1/groupversion_info.go | 36 + catalogd/api/v1/zz_generated.deepcopy.go | 227 ++++ catalogd/cmd/catalogd/main.go | 387 ++++++ ....operatorframework.io_clustercatalogs.yaml | 441 +++++++ catalogd/config/base/crd/kustomization.yaml | 6 + .../clustercatalogs/default-catalogs.yaml | 11 + .../config/base/default/kustomization.yaml | 17 + .../config/base/manager/catalogd_service.yaml | 24 + .../config/base/manager/kustomization.yaml | 17 + catalogd/config/base/manager/manager.yaml | 91 ++ .../base/manager/webhook/manifests.yaml | 27 + .../config/base/manager/webhook/patch.yaml | 20 + .../base/nginx-ingress/kustomization.yaml | 7 + .../resources/nginx_ingress.yaml | 17 + .../rbac/auth_proxy_client_clusterrole.yaml | 12 + .../config/base/rbac/auth_proxy_role.yaml | 20 + .../base/rbac/auth_proxy_role_binding.yaml | 15 + catalogd/config/base/rbac/kustomization.yaml | 20 + .../base/rbac/leader_election_role.yaml | 40 + .../rbac/leader_election_role_binding.yaml | 15 + catalogd/config/base/rbac/role.yaml | 32 + catalogd/config/base/rbac/role_binding.yaml | 15 + .../config/base/rbac/service_account.yaml | 8 + .../config/components/ca/kustomization.yaml | 10 + .../patches/manager_deployment_cacerts.yaml | 9 + .../components/ca/resources/issuers.yaml | 35 + .../registries-conf/kustomization.yaml | 7 + .../manager_e2e_registries_conf_patch.yaml | 17 + .../registries_conf_configmap.yaml | 11 + .../config/components/tls/kustomization.yaml | 21 + .../tls/patches/catalogd_service_port.yaml | 6 + .../tls/patches/catalogd_webhook.yaml | 3 + .../tls/patches/manager_deployment_certs.yaml | 12 + .../components/tls/resources/certificate.yaml | 19 + .../overlays/cert-manager/kustomization.yaml | 9 + .../config/overlays/e2e/kustomization.yaml | 12 + catalogd/config/rbac/role.yaml | 65 + .../samples/core_v1_clustercatalog.yaml | 11 + catalogd/crd-diff-config.yaml | 109 ++ catalogd/docs/fetching-catalog-contents.md | 204 ++++ catalogd/hack/scripts/demo-script.sh | 39 + catalogd/hack/scripts/generate-asciidemo.sh | 57 + .../hack/scripts/generate-gzip-asciidemo.sh | 57 + catalogd/hack/scripts/gzip-demo-script.sh | 29 + .../core/clustercatalog_controller.go | 443 +++++++ .../core/clustercatalog_controller_test.go | 1060 +++++++++++++++++ .../core/pull_secret_controller.go | 110 ++ .../core/pull_secret_controller_test.go | 95 ++ catalogd/internal/features/features.go | 14 + .../garbagecollection/garbage_collector.go | 94 ++ .../garbage_collector_test.go | 96 ++ catalogd/internal/k8sutil/k8sutil.go | 17 + catalogd/internal/k8sutil/k8sutil_test.go | 62 + catalogd/internal/metrics/metrics.go | 40 + catalogd/internal/serverutil/serverutil.go | 63 + catalogd/internal/source/containers_image.go | 425 +++++++ .../source/containers_image_internal_test.go | 130 ++ .../internal/source/containers_image_test.go | 477 ++++++++ catalogd/internal/source/unpacker.go | 72 ++ catalogd/internal/storage/localdir.go | 114 ++ catalogd/internal/storage/localdir_test.go | 438 +++++++ catalogd/internal/storage/storage.go | 19 + catalogd/internal/storage/suite_test.go | 29 + .../internal/third_party/server/server.go | 123 ++ catalogd/internal/version/version.go | 36 + .../webhook/cluster_catalog_webhook.go | 46 + .../webhook/cluster_catalog_webhook_test.go | 106 ++ catalogd/pprof/README.md | 195 +++ .../pprof/catalogd_apiserver_cpu_profile.pb | Bin 0 -> 8115 bytes .../pprof/catalogd_apiserver_heap_profile.pb | Bin 0 -> 25762 bytes catalogd/pprof/images/controller_metrics.png | Bin 0 -> 116782 bytes .../pprof/images/customapiserver_metrics.png | Bin 0 -> 131229 bytes .../images/kubeapiserver_alone_metrics.png | Bin 0 -> 120400 bytes .../pprof/images/kubeapiserver_metrics.png | Bin 0 -> 119718 bytes catalogd/pprof/kind.yaml | 11 + .../pprof/kubeapiserver_alone_cpu_profile.pb | 317 +++++ .../pprof/kubeapiserver_alone_heap_profile.pb | Bin 0 -> 402317 bytes catalogd/pprof/kubeapiserver_cpu_profile.pb | 290 +++++ catalogd/pprof/kubeapiserver_heap_profile.pb | Bin 0 -> 560491 bytes catalogd/pprof/manager_cpu_profile.pb | Bin 0 -> 3387 bytes catalogd/pprof/manager_heap_profile.pb | Bin 0 -> 55744 bytes catalogd/scripts/install.tpl.sh | 45 + catalogd/test/e2e/e2e_suite_test.go | 49 + catalogd/test/e2e/metrics_endpoint_test.go | 127 ++ catalogd/test/e2e/unpack_test.go | 109 ++ catalogd/test/e2e/util.go | 51 + .../tools/imageregistry/imagebuilder.yaml | 32 + catalogd/test/tools/imageregistry/imgreg.yaml | 75 ++ .../tools/imageregistry/pre-upgrade-setup.sh | 34 + catalogd/test/tools/imageregistry/registry.sh | 34 + catalogd/test/upgrade/unpack_test.go | 131 ++ catalogd/test/upgrade/upgrade_suite_test.go | 53 + .../testdata/catalogs/test-catalog.Dockerfile | 6 + .../catalogs/test-catalog/.indexignore | 2 + .../catalogs/test-catalog/catalog.yaml | 20 + .../catalogs/test-catalog/expected_all.json | 3 + cmd/{manager => operator-controller}/main.go | 2 +- config/base/manager/manager.yaml | 2 +- config/webhook/manifests.yaml | 27 + docs/contribute/developer.md | 27 +- go.mod | 13 +- go.sum | 10 +- internal/catalogmetadata/client/client.go | 3 +- .../catalogmetadata/client/client_test.go | 2 +- .../controllers/clustercatalog_controller.go | 2 +- .../clustercatalog_controller_test.go | 3 +- .../clusterextension_controller.go | 2 +- internal/resolve/catalog.go | 2 +- internal/resolve/catalog_test.go | 2 +- internal/scheme/scheme.go | 3 +- scripts/install.tpl.sh | 30 +- test/e2e/cluster_extension_install_test.go | 3 +- test/e2e/e2e_suite_test.go | 3 +- .../extension_developer_test.go | 3 +- test/upgrade-e2e/post_upgrade_test.go | 3 +- 136 files changed, 9669 insertions(+), 128 deletions(-) create mode 100644 .github/workflows/catalogd-crd-diff.yaml create mode 100644 .github/workflows/catalogd-demo.yaml create mode 100644 .github/workflows/catalogd-e2e.yaml create mode 100644 .idea/.gitignore create mode 100644 .idea/catalogd.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .tilt-support create mode 100644 catalogd/.dockerignore create mode 100644 catalogd/.gitignore create mode 100644 catalogd/Dockerfile create mode 100644 catalogd/Makefile create mode 100644 catalogd/README.md create mode 100644 catalogd/api/doc.go create mode 100644 catalogd/api/v1/clustercatalog_types.go create mode 100644 catalogd/api/v1/clustercatalog_types_test.go create mode 100644 catalogd/api/v1/groupversion_info.go create mode 100644 catalogd/api/v1/zz_generated.deepcopy.go create mode 100644 catalogd/cmd/catalogd/main.go create mode 100644 catalogd/config/base/crd/bases/olm.operatorframework.io_clustercatalogs.yaml create mode 100644 catalogd/config/base/crd/kustomization.yaml create mode 100644 catalogd/config/base/default/clustercatalogs/default-catalogs.yaml create mode 100644 catalogd/config/base/default/kustomization.yaml create mode 100644 catalogd/config/base/manager/catalogd_service.yaml create mode 100644 catalogd/config/base/manager/kustomization.yaml create mode 100644 catalogd/config/base/manager/manager.yaml create mode 100644 catalogd/config/base/manager/webhook/manifests.yaml create mode 100644 catalogd/config/base/manager/webhook/patch.yaml create mode 100644 catalogd/config/base/nginx-ingress/kustomization.yaml create mode 100644 catalogd/config/base/nginx-ingress/resources/nginx_ingress.yaml create mode 100644 catalogd/config/base/rbac/auth_proxy_client_clusterrole.yaml create mode 100644 catalogd/config/base/rbac/auth_proxy_role.yaml create mode 100644 catalogd/config/base/rbac/auth_proxy_role_binding.yaml create mode 100644 catalogd/config/base/rbac/kustomization.yaml create mode 100644 catalogd/config/base/rbac/leader_election_role.yaml create mode 100644 catalogd/config/base/rbac/leader_election_role_binding.yaml create mode 100644 catalogd/config/base/rbac/role.yaml create mode 100644 catalogd/config/base/rbac/role_binding.yaml create mode 100644 catalogd/config/base/rbac/service_account.yaml create mode 100644 catalogd/config/components/ca/kustomization.yaml create mode 100644 catalogd/config/components/ca/patches/manager_deployment_cacerts.yaml create mode 100644 catalogd/config/components/ca/resources/issuers.yaml create mode 100644 catalogd/config/components/registries-conf/kustomization.yaml create mode 100644 catalogd/config/components/registries-conf/manager_e2e_registries_conf_patch.yaml create mode 100644 catalogd/config/components/registries-conf/registries_conf_configmap.yaml create mode 100644 catalogd/config/components/tls/kustomization.yaml create mode 100644 catalogd/config/components/tls/patches/catalogd_service_port.yaml create mode 100644 catalogd/config/components/tls/patches/catalogd_webhook.yaml create mode 100644 catalogd/config/components/tls/patches/manager_deployment_certs.yaml create mode 100644 catalogd/config/components/tls/resources/certificate.yaml create mode 100644 catalogd/config/overlays/cert-manager/kustomization.yaml create mode 100644 catalogd/config/overlays/e2e/kustomization.yaml create mode 100644 catalogd/config/rbac/role.yaml create mode 100644 catalogd/config/samples/core_v1_clustercatalog.yaml create mode 100644 catalogd/crd-diff-config.yaml create mode 100644 catalogd/docs/fetching-catalog-contents.md create mode 100755 catalogd/hack/scripts/demo-script.sh create mode 100755 catalogd/hack/scripts/generate-asciidemo.sh create mode 100755 catalogd/hack/scripts/generate-gzip-asciidemo.sh create mode 100755 catalogd/hack/scripts/gzip-demo-script.sh create mode 100644 catalogd/internal/controllers/core/clustercatalog_controller.go create mode 100644 catalogd/internal/controllers/core/clustercatalog_controller_test.go create mode 100644 catalogd/internal/controllers/core/pull_secret_controller.go create mode 100644 catalogd/internal/controllers/core/pull_secret_controller_test.go create mode 100644 catalogd/internal/features/features.go create mode 100644 catalogd/internal/garbagecollection/garbage_collector.go create mode 100644 catalogd/internal/garbagecollection/garbage_collector_test.go create mode 100644 catalogd/internal/k8sutil/k8sutil.go create mode 100644 catalogd/internal/k8sutil/k8sutil_test.go create mode 100644 catalogd/internal/metrics/metrics.go create mode 100644 catalogd/internal/serverutil/serverutil.go create mode 100644 catalogd/internal/source/containers_image.go create mode 100644 catalogd/internal/source/containers_image_internal_test.go create mode 100644 catalogd/internal/source/containers_image_test.go create mode 100644 catalogd/internal/source/unpacker.go create mode 100644 catalogd/internal/storage/localdir.go create mode 100644 catalogd/internal/storage/localdir_test.go create mode 100644 catalogd/internal/storage/storage.go create mode 100644 catalogd/internal/storage/suite_test.go create mode 100644 catalogd/internal/third_party/server/server.go create mode 100644 catalogd/internal/version/version.go create mode 100644 catalogd/internal/webhook/cluster_catalog_webhook.go create mode 100644 catalogd/internal/webhook/cluster_catalog_webhook_test.go create mode 100644 catalogd/pprof/README.md create mode 100644 catalogd/pprof/catalogd_apiserver_cpu_profile.pb create mode 100644 catalogd/pprof/catalogd_apiserver_heap_profile.pb create mode 100644 catalogd/pprof/images/controller_metrics.png create mode 100644 catalogd/pprof/images/customapiserver_metrics.png create mode 100644 catalogd/pprof/images/kubeapiserver_alone_metrics.png create mode 100644 catalogd/pprof/images/kubeapiserver_metrics.png create mode 100644 catalogd/pprof/kind.yaml create mode 100644 catalogd/pprof/kubeapiserver_alone_cpu_profile.pb create mode 100644 catalogd/pprof/kubeapiserver_alone_heap_profile.pb create mode 100644 catalogd/pprof/kubeapiserver_cpu_profile.pb create mode 100644 catalogd/pprof/kubeapiserver_heap_profile.pb create mode 100644 catalogd/pprof/manager_cpu_profile.pb create mode 100644 catalogd/pprof/manager_heap_profile.pb create mode 100644 catalogd/scripts/install.tpl.sh create mode 100644 catalogd/test/e2e/e2e_suite_test.go create mode 100644 catalogd/test/e2e/metrics_endpoint_test.go create mode 100644 catalogd/test/e2e/unpack_test.go create mode 100644 catalogd/test/e2e/util.go create mode 100644 catalogd/test/tools/imageregistry/imagebuilder.yaml create mode 100644 catalogd/test/tools/imageregistry/imgreg.yaml create mode 100755 catalogd/test/tools/imageregistry/pre-upgrade-setup.sh create mode 100755 catalogd/test/tools/imageregistry/registry.sh create mode 100644 catalogd/test/upgrade/unpack_test.go create mode 100644 catalogd/test/upgrade/upgrade_suite_test.go create mode 100644 catalogd/testdata/catalogs/test-catalog.Dockerfile create mode 100644 catalogd/testdata/catalogs/test-catalog/.indexignore create mode 100644 catalogd/testdata/catalogs/test-catalog/catalog.yaml create mode 100644 catalogd/testdata/catalogs/test-catalog/expected_all.json rename cmd/{manager => operator-controller}/main.go (99%) create mode 100644 config/webhook/manifests.yaml diff --git a/.github/workflows/catalogd-crd-diff.yaml b/.github/workflows/catalogd-crd-diff.yaml new file mode 100644 index 000000000..d3c6ca099 --- /dev/null +++ b/.github/workflows/catalogd-crd-diff.yaml @@ -0,0 +1,19 @@ +name: catalogd-crd-diff +on: + pull_request: +jobs: + crd-diff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Run make verify-crd-compatibility + working-directory: catalogd + run: make verify-crd-compatibility CRD_DIFF_ORIGINAL_REF=${{ github.event.pull_request.base.sha }} CRD_DIFF_UPDATED_SOURCE="git://${{ github.event.pull_request.head.sha }}?path=config/base/crd/bases/olm.operatorframework.io_clustercatalogs.yaml" + diff --git a/.github/workflows/catalogd-demo.yaml b/.github/workflows/catalogd-demo.yaml new file mode 100644 index 000000000..68733fc13 --- /dev/null +++ b/.github/workflows/catalogd-demo.yaml @@ -0,0 +1,25 @@ +name: catalogd-demo + +on: + workflow_dispatch: + merge_group: + pull_request: + push: + branches: + - main + +jobs: + demo: + runs-on: ubuntu-latest + env: + TERM: linux + steps: + - run: sudo apt update && sudo apt install -y asciinema curl + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: "go.mod" + - name: Run Demo Update + working-directory: catalogd + run: make demo-update + diff --git a/.github/workflows/catalogd-e2e.yaml b/.github/workflows/catalogd-e2e.yaml new file mode 100644 index 000000000..06f592788 --- /dev/null +++ b/.github/workflows/catalogd-e2e.yaml @@ -0,0 +1,31 @@ +name: catalogd-e2e + +on: + workflow_dispatch: + merge_group: + pull_request: + push: + branches: + - main + +jobs: + e2e: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: "go.mod" + - name: Run E2e + working-directory: catalogd + run: make e2e + upgrade-e2e: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: "go.mod" + - name: Run the upgrade e2e test + working-directory: catalogd + run: make test-upgrade-e2e diff --git a/.github/workflows/tilt.yaml b/.github/workflows/tilt.yaml index 3a25fdb73..63ddc2a13 100644 --- a/.github/workflows/tilt.yaml +++ b/.github/workflows/tilt.yaml @@ -6,32 +6,20 @@ on: - 'api/**' - 'cmd/**' - 'config/**' + - 'catalogd/**' - 'internal/**' - 'pkg/**' - 'Tiltfile' + - '.tilt-support' merge_group: jobs: tilt: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - with: - repository: operator-framework/tilt-support - path: tilt-support - uses: actions/checkout@v4 with: path: operator-controller - - name: Get catalogd version - id: get-catalogd-version - run: | - cd operator-controller - echo "CATALOGD_VERSION=$(go list -mod=mod -m -f "{{.Version}}" github.com/operator-framework/catalogd)" >> "$GITHUB_OUTPUT" - - uses: actions/checkout@v4 - with: - repository: operator-framework/catalogd - path: catalogd - ref: "${{ steps.get-catalogd-version.outputs.CATALOGD_VERSION }}" - name: Install Go uses: actions/setup-go@v5 with: diff --git a/.goreleaser.yml b/.goreleaser.yml index 57e9dd8b6..d8c5d1a64 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -4,13 +4,30 @@ before: - go mod download builds: - id: operator-controller - main: ./cmd/manager/ - binary: manager + main: ./cmd/operator-controller/ + binary: operator-controller asmflags: "{{ .Env.GO_BUILD_ASMFLAGS }}" gcflags: "{{ .Env.GO_BUILD_GCFLAGS }}" ldflags: "{{ .Env.GO_BUILD_LDFLAGS }}" tags: - - "{{ .Env.GO_BUILD_TAGS }}" + - "{{ .Env.GO_BUILD_TAGS }}" + mod_timestamp: "{{ .CommitTimestamp }}" + goos: + - linux + goarch: + - amd64 + - arm64 + - ppc64le + - s390x + - id: catalogd + main: ./catalogd/cmd/catalogd/ + binary: catalogd + asmflags: "{{ .Env.GO_BUILD_ASMFLAGS }}" + gcflags: "{{ .Env.GO_BUILD_GCFLAGS }}" + ldflags: "{{ .Env.GO_BUILD_LDFLAGS }}" + tags: + - "{{ .Env.GO_BUILD_TAGS }}" + mod_timestamp: "{{ .CommitTimestamp }}" goos: - linux goarch: @@ -20,7 +37,7 @@ builds: - s390x dockers: - image_templates: - - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-amd64" + - "{{ .Env.OPERATOR_CONTROLLER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-amd64" dockerfile: Dockerfile goos: linux goarch: amd64 @@ -28,7 +45,7 @@ dockers: build_flag_templates: - "--platform=linux/amd64" - image_templates: - - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-arm64" + - "{{ .Env.OPERATOR_CONTROLLER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-arm64" dockerfile: Dockerfile goos: linux goarch: arm64 @@ -36,7 +53,7 @@ dockers: build_flag_templates: - "--platform=linux/arm64" - image_templates: - - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-ppc64le" + - "{{ .Env.OPERATOR_CONTROLLER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-ppc64le" dockerfile: Dockerfile goos: linux goarch: ppc64le @@ -44,20 +61,58 @@ dockers: build_flag_templates: - "--platform=linux/ppc64le" - image_templates: - - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-s390x" + - "{{ .Env.OPERATOR_CONTROLLER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-s390x" dockerfile: Dockerfile goos: linux goarch: s390x use: buildx build_flag_templates: - "--platform=linux/s390x" + - image_templates: + - "{{ .Env.CATALOGD_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-amd64" + dockerfile: catalogd/Dockerfile + goos: linux + goarch: amd64 + use: buildx + build_flag_templates: + - "--platform=linux/amd64" + - image_templates: + - "{{ .Env.CATALOGD_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-arm64" + dockerfile: catalogd/Dockerfile + goos: linux + goarch: arm64 + use: buildx + build_flag_templates: + - "--platform=linux/arm64" + - image_templates: + - "{{ .Env.CATALOGD_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-ppc64le" + dockerfile: catalogd/Dockerfile + goos: linux + goarch: ppc64le + use: buildx + build_flag_templates: + - "--platform=linux/ppc64le" + - image_templates: + - "{{ .Env.CATALOGD_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-s390x" + dockerfile: catalogd/Dockerfile + goos: linux + goarch: s390x + use: buildx + build_flag_templates: + - "--platform=linux/s390x" docker_manifests: - - name_template: "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}" + - name_template: "{{ .Env.OPERATOR_CONTROLLER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}" + image_templates: + - "{{ .Env.OPERATOR_CONTROLLER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-amd64" + - "{{ .Env.OPERATOR_CONTROLLER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-arm64" + - "{{ .Env.OPERATOR_CONTROLLER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-ppc64le" + - "{{ .Env.OPERATOR_CONTROLLER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-s390x" + - name_template: "{{ .Env.CATALOGD_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}" image_templates: - - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-amd64" - - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-arm64" - - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-ppc64le" - - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-s390x" + - "{{ .Env.CATALOGD_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-amd64" + - "{{ .Env.CATALOGD_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-arm64" + - "{{ .Env.CATALOGD_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-ppc64le" + - "{{ .Env.CATALOGD_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-s390x" checksum: name_template: 'checksums.txt' snapshot: diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..13566b81b --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/catalogd.iml b/.idea/catalogd.iml new file mode 100644 index 000000000..5e764c4f0 --- /dev/null +++ b/.idea/catalogd.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..805dd8395 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.tilt-support b/.tilt-support new file mode 100644 index 000000000..c55d2851d --- /dev/null +++ b/.tilt-support @@ -0,0 +1,151 @@ +load('ext://restart_process', 'docker_build_with_restart') +load('ext://cert_manager', 'deploy_cert_manager') + + +def deploy_cert_manager_if_needed(): + cert_manager_var = '__CERT_MANAGER__' + if os.getenv(cert_manager_var) != '1': + deploy_cert_manager(version="v1.15.3") + os.putenv(cert_manager_var, '1') + + +# Set up our build helper image that has delve in it. We use a helper so parallel image builds don't all simultaneously +# install delve. Instead, they all wait for this build to complete, and then proceed in parallel. +docker_build( + ref='helper', + context='.', + build_args={'GO_VERSION': '1.23'}, + dockerfile_contents=''' +ARG GO_VERSION +FROM golang:${GO_VERSION} +ARG GO_VERSION +RUN CGO_ENABLED=0 go install github.com/go-delve/delve/cmd/dlv@v${GO_VERSION} +''' +) + + +def build_binary(repo, binary, deps, image, tags="", debug=True): + gcflags = '' + if debug: + gcflags = "-gcflags 'all=-N -l'" + + # Treat the main binary as a local resource, so we can automatically rebuild it when any of the deps change. This + # builds it locally, targeting linux, so it can run in a linux container. + binary_name = binary.split("/")[-1] + local_resource( + '{}_{}_binary'.format(repo, binary_name), + cmd=''' +mkdir -p .tiltbuild/bin +CGO_ENABLED=0 GOOS=linux go build {tags} {gcflags} -o .tiltbuild/bin/{binary_name} {binary} +'''.format(repo=repo, binary_name=binary_name, binary=binary, gcflags=gcflags, tags=tags), + deps=deps + ) + + entrypoint = ['/{}'.format(binary_name)] + if debug: + entrypoint = ['/dlv', '--accept-multiclient', '--api-version=2', '--headless=true', '--listen', ':30000', 'exec', '--continue', '--'] + entrypoint + + # Configure our image build. If the file in live_update.sync (.tiltbuild/bin/$binary) changes, Tilt + # copies it to the running container and restarts it. + docker_build_with_restart( + # This has to match an image in the k8s_yaml we call below, so Tilt knows to use this image for our Deployment, + # instead of the actual image specified in the yaml. + ref='{image}:{binary_name}'.format(image=image, binary_name=binary_name), + # This is the `docker build` context, and because we're only copying in the binary we've already had Tilt build + # locally, we set the context to the directory containing the binary. + context='.tiltbuild/bin', + # We use a slimmed-down Dockerfile that only has $binary in it. + dockerfile_contents=''' +FROM gcr.io/distroless/static:debug +WORKDIR / +COPY --from=helper /go/bin/dlv / +COPY {} / + '''.format(binary_name), + # The set of files Tilt should include in the build. In this case, it's just the binary we built above. + only=binary_name, + # If .tiltbuild/bin/$binary changes, Tilt will copy it into the running container and restart the process. + live_update=[ + sync('.tiltbuild/bin/{}'.format(binary_name), '/{}'.format(binary_name)), + ], + # The command to run in the container. + entrypoint=entrypoint, + ) + + +def process_yaml(yaml): + if type(yaml) == 'string': + objects = read_yaml_stream(yaml) + elif type(yaml) == 'blob': + objects = decode_yaml_stream(yaml) + else: + fail('expected a string or blob, got: {}'.format(type(yaml))) + + for o in objects: + # For Tilt's live_update functionality to work, we have to run the container as root. Remove any PSA labels + # to allow this. + if o['kind'] == 'Namespace' and 'labels' in o['metadata']: + labels_to_delete = [label for label in o['metadata']['labels'] if label.startswith('pod-security.kubernetes.io')] + for label in labels_to_delete: + o['metadata']['labels'].pop(label) + + if o['kind'] != 'Deployment': + # We only need to modify Deployments, so we can skip this + continue + + # For Tilt's live_update functionality to work, we have to run the container as root. Otherwise, Tilt won't + # be able to untar the updated binary in the container's file system (this is how live update + # works). If there are any securityContexts, remove them. + if "securityContext" in o['spec']['template']['spec']: + o['spec']['template']['spec'].pop('securityContext') + for c in o['spec']['template']['spec']['containers']: + if "securityContext" in c: + c.pop('securityContext') + + # If multiple Deployment manifests all use the same image but use different entrypoints to change the binary, + # we have to adjust each Deployment to use a different image. Tilt needs each Deployment's image to be + # unique. We replace the tag with what is effectively :$binary, e.g. :helm. + for c in o['spec']['template']['spec']['containers']: + if c['name'] == 'kube-rbac-proxy': + continue + + command = c['command'][0] + if command.startswith('./'): + command = command.removeprefix('./') + elif command.startswith('/'): + command = command.removeprefix('/') + + image_without_tag = c['image'].rsplit(':', 1)[0] + + # Update the image so instead of :$tag it's :$binary + c['image'] = '{}:{}'.format(image_without_tag, command) + + # Now apply all the yaml + # We are using allow_duplicates=True here as both + # operator-controller and catalogd will be installed in the same + # namespace "olmv1-system" as of https://github.com/operator-framework/operator-controller/pull/888 + # and https://github.com/operator-framework/catalogd/pull/283 + k8s_yaml(encode_yaml_stream(objects), allow_duplicates=True) + + +# data format: +# { +# 'image': 'quay.io/operator-framework/rukpak', +# 'yaml': 'manifests/overlays/cert-manager', +# 'binaries': { +# 'core': 'core', +# 'crdvalidator': 'crd-validation-webhook', +# 'helm': 'helm-provisioner', +# 'webhooks': 'rukpak-webhooks', +# }, +# 'deps': ['api', 'cmd/binary_name', 'internal', 'pkg'], +# }, +def deploy_repo(repo, data, tags="", debug=True): + print('Deploying repo {}'.format(repo)) + deploy_cert_manager_if_needed() + + local_port = data['starting_debug_port'] + for binary, deployment in data['binaries'].items(): + build_binary(repo, binary, data['deps'], data['image'], tags, debug) + k8s_resource(deployment, port_forwards=['{}:30000'.format(local_port)]) + local_port += 1 + process_yaml(kustomize(data['yaml'])) diff --git a/Dockerfile b/Dockerfile index 03c737e3f..0fe53b71e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,11 +2,9 @@ # required and is intended to be built only with the # 'make build' or 'make release' targets. FROM gcr.io/distroless/static:nonroot - WORKDIR / - -COPY manager manager - +COPY operator-controller operator-controller EXPOSE 8080 - USER 65532:65532 + +ENTRYPOINT ["/operator-controller"] \ No newline at end of file diff --git a/Makefile b/Makefile index b18aca141..4d2209a72 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,11 @@ IMAGE_REPO := quay.io/operator-framework/operator-controller endif export IMAGE_REPO +ifeq ($(origin CATALOG_IMAGE_REPO), undefined) +CATALOG_IMAGE_REPO := quay.io/operator-framework/catalogd +endif +export CATALOG_IMAGE_REPO + ifeq ($(origin IMAGE_TAG), undefined) IMAGE_TAG := devel endif @@ -23,7 +28,6 @@ IMG := $(IMAGE_REPO):$(IMAGE_TAG) # Define dependency versions (use go.mod if we also use Go code from dependency) export CERT_MGR_VERSION := v1.15.3 -export CATALOGD_VERSION := $(shell go list -mod=mod -m -f "{{.Version}}" github.com/operator-framework/catalogd) export WAIT_TIMEOUT := 60s # Install default ClusterCatalogs @@ -99,9 +103,14 @@ tidy: #HELP Update dependencies. # Force tidy to use the version already in go.mod $(Q)go mod tidy -go=$(GOLANG_VERSION) + .PHONY: manifests -manifests: $(CONTROLLER_GEN) #EXHELP Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/base/crd/bases output:rbac:artifacts:config=config/base/rbac +manifests: $(CONTROLLER_GEN) #EXHELP Generate WebhookConfiguration, ClusterRole, and CustomResourceDefinition objects. + # To generate the manifests used and do not use catalogd directory + $(CONTROLLER_GEN) rbac:roleName=manager-role paths=./internal/... output:rbac:artifacts:config=config/base/rbac + $(CONTROLLER_GEN) crd paths=./api/... output:crd:artifacts:config=config/base/crd/bases + # To generate the manifests for catalogd + $(MAKE) -C catalogd generate .PHONY: generate generate: $(CONTROLLER_GEN) #EXHELP Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. @@ -138,7 +147,7 @@ verify-crd-compatibility: $(CRD_DIFF) manifests $(CRD_DIFF) --config="${CRD_DIFF_CONFIG}" "git://${CRD_DIFF_ORIGINAL_REF}?path=config/base/crd/bases/olm.operatorframework.io_clusterextensions.yaml" ${CRD_DIFF_UPDATED_SOURCE} .PHONY: test -test: manifests generate fmt vet test-unit test-e2e #HELP Run all tests. +test: manifests generate generate-catalogd fmt vet test-unit test-e2e #HELP Run all tests. .PHONY: e2e e2e: #EXHELP Run the e2e tests. @@ -159,7 +168,7 @@ test-ext-dev-e2e: $(OPERATOR_SDK) $(KUSTOMIZE) $(KIND) #HELP Run extension creat go test -count=1 -v ./test/extension-developer-e2e/... ENVTEST_VERSION := $(shell go list -m k8s.io/client-go | cut -d" " -f2 | sed 's/^v0\.\([[:digit:]]\{1,\}\)\.[[:digit:]]\{1,\}$$/1.\1.x/') -UNIT_TEST_DIRS := $(shell go list ./... | grep -v /test/) +UNIT_TEST_DIRS := $(shell go list ./... | grep -v /test/ | grep -v /catalogd/test/) COVERAGE_UNIT_DIR := $(ROOT_DIR)/coverage/unit .PHONY: envtest-k8s-bins #HELP Uses setup-envtest to download and install the binaries required to run ENVTEST-test based locally at the project/bin directory. @@ -229,14 +238,16 @@ e2e-coverage: COVERAGE_OUTPUT=./coverage/e2e.out ./hack/test/e2e-coverage.sh .PHONY: kind-load -kind-load: $(KIND) #EXHELP Loads the currently constructed image onto the cluster. +kind-load: $(KIND) #EXHELP Loads the currently constructed images into the KIND cluster. $(CONTAINER_RUNTIME) save $(IMG) | $(KIND) load image-archive /dev/stdin --name $(KIND_CLUSTER_NAME) + IMAGE_REPO=$(CATALOG_IMAGE_REPO) KIND_CLUSTER_NAME=$(KIND_CLUSTER_NAME) $(MAKE) -C catalogd kind-load .PHONY: kind-deploy -kind-deploy: export MANIFEST="./operator-controller.yaml" -kind-deploy: manifests $(KUSTOMIZE) #EXHELP Install controller and dependencies onto the kind cluster. - $(KUSTOMIZE) build $(KUSTOMIZE_BUILD_DIR) > operator-controller.yaml - envsubst '$$CATALOGD_VERSION,$$CERT_MGR_VERSION,$$INSTALL_DEFAULT_CATALOGS,$$MANIFEST' < scripts/install.tpl.sh | bash -s +kind-deploy: export MANIFEST := ./operator-controller.yaml +kind-deploy: manifests $(KUSTOMIZE) + ($(KUSTOMIZE) build $(KUSTOMIZE_BUILD_DIR) && echo "---" && $(KUSTOMIZE) build catalogd/config/overlays/cert-manager | sed "s/cert-git-version/cert-$(VERSION)/g") > $(MANIFEST) + envsubst '$$CERT_MGR_VERSION,$$INSTALL_DEFAULT_CATALOGS,$$MANIFEST' < scripts/install.tpl.sh | bash -s + .PHONY: kind-cluster kind-cluster: $(KIND) #EXHELP Standup a kind cluster. @@ -269,7 +280,7 @@ export GO_BUILD_FLAGS := export GO_BUILD_LDFLAGS := -s -w \ -X '$(VERSION_PATH).version=$(VERSION)' \ -BINARIES=manager +BINARIES=operator-controller $(BINARIES): go build $(GO_BUILD_FLAGS) -tags '$(GO_BUILD_TAGS)' -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o $(BUILDBIN)/$@ ./cmd/$@ @@ -293,8 +304,9 @@ go-build-linux: $(BINARIES) run: docker-build kind-cluster kind-load kind-deploy #HELP Build the operator-controller then deploy it into a new kind cluster. .PHONY: docker-build -docker-build: build-linux #EXHELP Build docker image for operator-controller with GOOS=linux and local GOARCH. +docker-build: build-linux #EXHELP Build docker image for operator-controller and catalog with GOOS=linux and local GOARCH. $(CONTAINER_RUNTIME) build -t $(IMG) -f Dockerfile ./bin/linux + IMAGE_REPO=$(CATALOG_IMAGE_REPO) $(MAKE) -C catalogd build-container #SECTION Release ifeq ($(origin ENABLE_RELEASE_PIPELINE), undefined) @@ -309,34 +321,32 @@ export GORELEASER_ARGS .PHONY: release release: $(GORELEASER) #EXHELP Runs goreleaser for the operator-controller. By default, this will run only as a snapshot and will not publish any artifacts unless it is run with different arguments. To override the arguments, run with "GORELEASER_ARGS=...". When run as a github action from a tag, this target will publish a full release. - $(GORELEASER) $(GORELEASER_ARGS) + OPERATOR_CONTROLLER_IMAGE_REPO=$(IMAGE_REPO) CATALOGD_IMAGE_REPO=$(CATALOG_IMAGE_REPO) $(GORELEASER) $(GORELEASER_ARGS) .PHONY: quickstart -quickstart: export MANIFEST := https://github.com/operator-framework/operator-controller/releases/download/$(VERSION)/operator-controller.yaml -quickstart: $(KUSTOMIZE) manifests #EXHELP Generate the installation release manifests and scripts. - $(KUSTOMIZE) build $(KUSTOMIZE_BUILD_DIR) | sed "s/:devel/:$(VERSION)/g" > operator-controller.yaml - envsubst '$$CATALOGD_VERSION,$$CERT_MGR_VERSION,$$INSTALL_DEFAULT_CATALOGS,$$MANIFEST' < scripts/install.tpl.sh > install.sh +quickstart: export MANIFEST := ./operator-controller.yaml +quickstart: $(KUSTOMIZE) manifests #EXHELP Generate the unified installation release manifests and scripts. + ($(KUSTOMIZE) build $(KUSTOMIZE_BUILD_DIR) && echo "---" && $(KUSTOMIZE) build catalogd/config/overlays/cert-manager | sed "s/cert-git-version/cert-$(VERSION)/g") > $(MANIFEST) + envsubst '$$CERT_MGR_VERSION,$$INSTALL_DEFAULT_CATALOGS,$$MANIFEST' < scripts/install.tpl.sh > install.sh ##@ Docs .PHONY: crd-ref-docs OPERATOR_CONTROLLER_API_REFERENCE_FILENAME := operator-controller-api-reference.md CATALOGD_API_REFERENCE_FILENAME := catalogd-api-reference.md -CATALOGD_TMP_DIR := $(ROOT_DIR)/.catalogd-tmp/ API_REFERENCE_DIR := $(ROOT_DIR)/docs/api-reference + crd-ref-docs: $(CRD_REF_DOCS) #EXHELP Generate the API Reference Documents. rm -f $(API_REFERENCE_DIR)/$(OPERATOR_CONTROLLER_API_REFERENCE_FILENAME) $(CRD_REF_DOCS) --source-path=$(ROOT_DIR)/api \ --config=$(API_REFERENCE_DIR)/crd-ref-docs-gen-config.yaml \ --renderer=markdown --output-path=$(API_REFERENCE_DIR)/$(OPERATOR_CONTROLLER_API_REFERENCE_FILENAME); - rm -rf $(CATALOGD_TMP_DIR) - git clone --depth 1 --branch $(CATALOGD_VERSION) https://github.com/operator-framework/catalogd $(CATALOGD_TMP_DIR) + rm -f $(API_REFERENCE_DIR)/$(CATALOGD_API_REFERENCE_FILENAME) - $(CRD_REF_DOCS) --source-path=$(CATALOGD_TMP_DIR)/api \ + $(CRD_REF_DOCS) --source-path=$(ROOT_DIR)/catalogd/api \ --config=$(API_REFERENCE_DIR)/crd-ref-docs-gen-config.yaml \ - --renderer=markdown --output-path=$(API_REFERENCE_DIR)/$(CATALOGD_API_REFERENCE_FILENAME) - rm -rf $(CATALOGD_TMP_DIR)/ - + --renderer=markdown --output-path=$(API_REFERENCE_DIR)/$(CATALOGD_API_REFERENCE_FILENAME); + VENVDIR := $(abspath docs/.venv) .PHONY: build-docs diff --git a/Tiltfile b/Tiltfile index 10c4362e1..7aa07e811 100644 --- a/Tiltfile +++ b/Tiltfile @@ -1,23 +1,24 @@ -if not os.path.exists('../tilt-support'): - fail('Please clone https://github.com/operator-framework/tilt-support to ../tilt-support') +load('.tilt-support', 'deploy_repo') -load('../tilt-support/Tiltfile', 'deploy_repo') - -config.define_string_list('repos', args=True) -cfg = config.parse() -repos = cfg.get('repos', ['operator-controller', 'catalogd']) - -repo = { +operator_controller = { 'image': 'quay.io/operator-framework/operator-controller', 'yaml': 'config/overlays/cert-manager', 'binaries': { - 'manager': 'operator-controller-controller-manager', + './cmd/operator-controller': 'operator-controller-controller-manager', }, + 'deps': ['api', 'cmd/operator-controller', 'internal', 'pkg', 'go.mod', 'go.sum'], 'starting_debug_port': 30000, } +deploy_repo('operator-controller', operator_controller, '-tags containers_image_openpgp') + +catalogd = { + 'image': 'quay.io/operator-framework/catalogd', + 'yaml': 'catalogd/config/overlays/cert-manager', + 'binaries': { + './catalogd/cmd/catalogd': 'catalogd-controller-manager', + }, + 'deps': ['catalogd/api', 'catalogd/cmd/catalogd', 'catalogd/internal', 'catalogd/pkg', 'go.mod', 'go.sum'], + 'starting_debug_port': 20000, +} -for r in repos: - if r == 'operator-controller': - deploy_repo('operator-controller', repo, '-tags containers_image_openpgp') - else: - include('../{}/Tiltfile'.format(r)) +deploy_repo('catalogd', catalogd, '-tags containers_image_openpgp') diff --git a/catalogd/.dockerignore b/catalogd/.dockerignore new file mode 100644 index 000000000..83f42b89a --- /dev/null +++ b/catalogd/.dockerignore @@ -0,0 +1,8 @@ +# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file +# Ignore test and tool binaries. +bin/controller-gen +bin/goreleaser +bin/kustomize +bin/envtest +testbin/ +.tiltbuild/ diff --git a/catalogd/.gitignore b/catalogd/.gitignore new file mode 100644 index 000000000..8ee34b8f6 --- /dev/null +++ b/catalogd/.gitignore @@ -0,0 +1,21 @@ + +# Binaries for programs and plugins +bin + +# Kubernetes Generated files - skip generated files, except for vendored files + +!vendor/**/zz_generated.* + +# Dependency directories +vendor/ +bin/ +dist/ +cover.out + +# Release output +catalogd.yaml +install.sh + +.tiltbuild/ +.vscode +.idea diff --git a/catalogd/Dockerfile b/catalogd/Dockerfile new file mode 100644 index 000000000..d0833c1fe --- /dev/null +++ b/catalogd/Dockerfile @@ -0,0 +1,8 @@ +# Use distroless as minimal base image to package the manager binary +# Refer to https://github.com/GoogleContainerTools/distroless for more details +FROM gcr.io/distroless/static:nonroot +WORKDIR / +COPY catalogd catalogd +USER 65532:65532 + +ENTRYPOINT ["/catalogd"] \ No newline at end of file diff --git a/catalogd/Makefile b/catalogd/Makefile new file mode 100644 index 000000000..1059554bb --- /dev/null +++ b/catalogd/Makefile @@ -0,0 +1,229 @@ +# Setting SHELL to bash allows bash commands to be executed by recipes. +# Options are set to exit when a recipe line exits non-zero or a piped command fails. +SHELL := /usr/bin/env bash -o pipefail +.SHELLFLAGS := -ec + +ifeq ($(origin IMAGE_REPO), undefined) +IMAGE_REPO := quay.io/operator-framework/catalogd +endif +export IMAGE_REPO + +ifeq ($(origin IMAGE_TAG), undefined) +IMAGE_TAG := devel +endif +export IMAGE_TAG + +IMAGE := $(IMAGE_REPO):$(IMAGE_TAG) + +ifneq (, $(shell command -v docker 2>/dev/null)) +CONTAINER_RUNTIME := docker +else ifneq (, $(shell command -v podman 2>/dev/null)) +CONTAINER_RUNTIME := podman +else +$(warning Could not find docker or podman in path! This may result in targets requiring a container runtime failing!) +endif + +# For standard development and release flows, we use the config/overlays/cert-manager overlay. +KUSTOMIZE_OVERLAY := config/overlays/cert-manager + +# bingo manages consistent tooling versions for things like kind, kustomize, etc. +include ./../.bingo/Variables.mk + +# Dependencies +export CERT_MGR_VERSION := v1.15.3 +ENVTEST_SERVER_VERSION := $(shell go list -m k8s.io/client-go | cut -d" " -f2 | sed 's/^v0\.\([[:digit:]]\{1,\}\)\.[[:digit:]]\{1,\}$$/1.\1.x/') + +# Cluster configuration +ifeq ($(origin KIND_CLUSTER_NAME), undefined) +KIND_CLUSTER_NAME := catalogd +endif + +# E2E configuration +TESTDATA_DIR := testdata + +CATALOGD_NAMESPACE := olmv1-system +KIND_CLUSTER_IMAGE := kindest/node:v1.30.0@sha256:047357ac0cfea04663786a612ba1eaba9702bef25227a794b52890dd8bcd692e + +##@ General + +# The help target prints out all targets with their descriptions organized +# beneath their categories. The categories are represented by '##@' and the +# target descriptions by '##'. The awk commands is responsible for reading the +# entire set of makefiles included in this invocation, looking for lines of the +# file as xyz: ## something, and then pretty-format the target and help. Then, +# if there's a line with ##@ something, that gets pretty-printed as a category. +# More info on the usage of ANSI control characters for terminal formatting: +# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters +# More info on the awk command: +# http://linuxcommand.org/lc3_adv_awk.php + +.PHONY: help +help: ## Display this help. + awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) +.DEFAULT_GOAL := help + +##@ Development + +clean: ## Remove binaries and test artifacts + rm -rf bin + +.PHONY: generate +generate: $(CONTROLLER_GEN) ## Generate code and manifests. + $(CONTROLLER_GEN) object:headerFile="../hack/boilerplate.go.txt" paths="./..." + $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/base/crd/bases output:rbac:artifacts:config=config/base/rbac output:webhook:artifacts:config=config/base/manager/webhook/ + +FOCUS := $(if $(TEST),-v -focus "$(TEST)") +ifeq ($(origin E2E_FLAGS), undefined) +E2E_FLAGS := +endif +test-e2e: $(GINKGO) ## Run the e2e tests on existing cluster + $(GINKGO) $(E2E_FLAGS) -trace -vv $(FOCUS) test/e2e + +e2e: KIND_CLUSTER_NAME := catalogd-e2e +e2e: ISSUER_KIND := Issuer +e2e: ISSUER_NAME := selfsigned-issuer +e2e: KUSTOMIZE_OVERLAY := config/overlays/e2e +e2e: run image-registry test-e2e kind-cluster-cleanup ## Run e2e test suite on local kind cluster + +image-registry: ## Setup in-cluster image registry + ./test/tools/imageregistry/registry.sh $(ISSUER_KIND) $(ISSUER_NAME) + +.PHONY: verify-crd-compatibility +CRD_DIFF_ORIGINAL_REF := main +CRD_DIFF_UPDATED_SOURCE := file://config/base/crd/bases/olm.operatorframework.io_clustercatalogs.yaml +CRD_DIFF_CONFIG := crd-diff-config.yaml +verify-crd-compatibility: $(CRD_DIFF) + @if git show ${CRD_DIFF_ORIGINAL_REF}:config/base/crd/bases/olm.operatorframework.io_clustercatalogs.yaml > /dev/null 2>&1; then \ + echo "Running CRD diff..."; \ + $(CRD_DIFF) --config="${CRD_DIFF_CONFIG}" "git://${CRD_DIFF_ORIGINAL_REF}?path=config/base/crd/bases/olm.operatorframework.io_clustercatalogs.yaml" ${CRD_DIFF_UPDATED_SOURCE}; \ + else \ + echo "Skipping CRD diff: CRD does not exist in ${CRD_DIFF_ORIGINAL_REF}"; \ + fi + + +## image-registry target has to come after run-latest-release, +## because the image-registry depends on the olm-ca issuer. +.PHONY: test-upgrade-e2e +test-upgrade-e2e: export TEST_CLUSTER_CATALOG_NAME := test-catalog +test-upgrade-e2e: export TEST_CLUSTER_CATALOG_IMAGE := docker-registry.catalogd-e2e.svc:5000/test-catalog:e2e +test-upgrade-e2e: ISSUER_KIND=ClusterIssuer +test-upgrade-e2e: ISSUER_NAME=olmv1-ca +test-upgrade-e2e: kind-cluster cert-manager build-container kind-load run-latest-release image-registry pre-upgrade-setup only-deploy-manifest wait post-upgrade-checks kind-cluster-cleanup ## Run upgrade e2e tests on a local kind cluster + +pre-upgrade-setup: + ./test/tools/imageregistry/pre-upgrade-setup.sh ${TEST_CLUSTER_CATALOG_IMAGE} ${TEST_CLUSTER_CATALOG_NAME} + +.PHONY: run-latest-release +run-latest-release: + curl -L -s https://github.com/operator-framework/catalogd/releases/latest/download/install.sh | bash -s + +.PHONY: post-upgrade-checks +post-upgrade-checks: $(GINKGO) + $(GINKGO) $(E2E_FLAGS) -trace -vv $(FOCUS) test/upgrade + +##@ Build + +BINARIES=catalogd +LINUX_BINARIES=$(join $(addprefix linux/,$(BINARIES)), ) + +# Build info +ifeq ($(origin VERSION), undefined) +VERSION := $(shell git describe --tags --always --dirty) +endif +export VERSION + +export VERSION_PKG := $(shell go list -m)/internal/version + +export GIT_COMMIT := $(shell git rev-parse HEAD) +export GIT_VERSION := $(shell git describe --tags --always --dirty) +export GIT_TREE_STATE := $(shell [ -z "$(shell git status --porcelain)" ] && echo "clean" || echo "dirty") +export GIT_COMMIT_DATE := $(shell TZ=UTC0 git show --quiet --date=format:'%Y-%m-%dT%H:%M:%SZ' --format="%cd") + +export CGO_ENABLED := 0 +export GO_BUILD_ASMFLAGS := all=-trimpath=${PWD} +export GO_BUILD_LDFLAGS := -s -w \ + -X "$(VERSION_PKG).gitVersion=$(GIT_VERSION)" \ + -X "$(VERSION_PKG).gitCommit=$(GIT_COMMIT)" \ + -X "$(VERSION_PKG).gitTreeState=$(GIT_TREE_STATE)" \ + -X "$(VERSION_PKG).commitDate=$(GIT_COMMIT_DATE)" +export GO_BUILD_GCFLAGS := all=-trimpath=${PWD} +export GO_BUILD_TAGS := containers_image_openpgp + +BUILDCMD = go build -tags '$(GO_BUILD_TAGS)' -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o $(BUILDBIN)/$(notdir $@) ./cmd/$(notdir $@) + +.PHONY: build-deps +build-deps: generate + +.PHONY: build go-build-local $(BINARIES) +build: build-deps go-build-local ## Build binaries for current GOOS and GOARCH. +go-build-local: $(BINARIES) +$(BINARIES): BUILDBIN = bin +$(BINARIES): + $(BUILDCMD) + +.PHONY: build-linux go-build-linux $(LINUX_BINARIES) +build-linux: build-deps go-build-linux ## Build binaries for GOOS=linux and local GOARCH. +go-build-linux: $(LINUX_BINARIES) +$(LINUX_BINARIES): BUILDBIN = bin/linux +$(LINUX_BINARIES): + GOOS=linux $(BUILDCMD) + + +.PHONY: run +run: generate kind-cluster install ## Create a kind cluster and install a local build of catalogd + +.PHONY: build-container +build-container: build-linux ## Build docker image for catalogd. + $(CONTAINER_RUNTIME) build -f Dockerfile -t $(IMAGE) ./bin/linux + +##@ Deploy + +.PHONY: kind-cluster +kind-cluster: $(KIND) kind-cluster-cleanup ## Standup a kind cluster + $(KIND) create cluster --name $(KIND_CLUSTER_NAME) --image $(KIND_CLUSTER_IMAGE) + $(KIND) export kubeconfig --name $(KIND_CLUSTER_NAME) + +.PHONY: kind-cluster-cleanup +kind-cluster-cleanup: $(KIND) ## Delete the kind cluster + $(KIND) delete cluster --name $(KIND_CLUSTER_NAME) + +.PHONY: kind-load +kind-load: check-cluster $(KIND) ## Load the built images onto the local cluster + $(CONTAINER_RUNTIME) save $(IMAGE) | $(KIND) load image-archive /dev/stdin --name $(KIND_CLUSTER_NAME) + +.PHONY: install +install: check-cluster build-container kind-load deploy wait ## Install local catalogd to an existing cluster + +.PHONY: deploy +deploy: export MANIFEST="./catalogd.yaml" +deploy: export DEFAULT_CATALOGS="./config/base/default/clustercatalogs/default-catalogs.yaml" +deploy: $(KUSTOMIZE) ## Deploy Catalogd to the K8s cluster specified in ~/.kube/config with cert-manager and default clustercatalogs + cd config/base/manager && $(KUSTOMIZE) edit set image controller=$(IMAGE) && cd ../../.. + $(KUSTOMIZE) build $(KUSTOMIZE_OVERLAY) | sed "s/cert-git-version/cert-$(GIT_VERSION)/g" > catalogd.yaml + envsubst '$$CERT_MGR_VERSION,$$MANIFEST,$$DEFAULT_CATALOGS' < scripts/install.tpl.sh | bash -s + +.PHONY: only-deploy-manifest +only-deploy-manifest: $(KUSTOMIZE) ## Deploy just the Catalogd manifest--used in e2e testing where cert-manager is installed in a separate step + cd config/base/manager && $(KUSTOMIZE) edit set image controller=$(IMAGE) + $(KUSTOMIZE) build $(KUSTOMIZE_OVERLAY) | kubectl apply -f - + +wait: + kubectl wait --for=condition=Available --namespace=$(CATALOGD_NAMESPACE) deployment/catalogd-controller-manager --timeout=60s + kubectl wait --for=condition=Ready --namespace=$(CATALOGD_NAMESPACE) certificate/catalogd-service-cert # Avoid upgrade test flakes when reissuing cert + + +.PHONY: cert-manager +cert-manager: + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/${CERT_MGR_VERSION}/cert-manager.yaml + kubectl wait --for=condition=Available --namespace=cert-manager deployment/cert-manager-webhook --timeout=60s + +.PHONY: demo-update +demo-update: + hack/scripts/generate-asciidemo.sh + +.PHONY: check-cluster +check-cluster: + @kubectl config current-context >/dev/null 2>&1 || ( \ + echo "Error: Could not get current Kubernetes context. Maybe use 'run' or 'e2e' targets first?"; \ + exit 1; \ + ) diff --git a/catalogd/README.md b/catalogd/README.md new file mode 100644 index 000000000..04a462f92 --- /dev/null +++ b/catalogd/README.md @@ -0,0 +1,169 @@ +# catalogd + +Catalogd is a Kubernetes extension that unpacks [file-based catalog (FBC)](https://olm.operatorframework.io/docs/reference/file-based-catalogs/#docs) content for on-cluster clients. Currently, catalogd unpacks FBC content that is packaged and distributed as container images. The catalogd road map includes plans for unpacking other content sources, such as Git repositories and OCI artifacts. For more information, see the catalogd [issues](https://github.com/operator-framework/catalogd/issues/) page. + +Catalogd helps customers discover installable content by hosting catalog metadata for Kubernetes extensions, such as Operators and controllers. For more information on the Operator Lifecycle Manager (OLM) v1 suite of microservices, see the [documentation](https://github.com/operator-framework/operator-controller/tree/main/docs) for the Operator Controller. + +## Quickstart DEMO +[![asciicast](https://asciinema.org/a/682344.svg)](https://asciinema.org/a/682344) + +## Quickstart Steps +Procedure steps marked with an asterisk (`*`) are likely to change with future API updates. + +**NOTE:** The examples below use the `-k` flag in curl to skip validating the TLS certificates. This is for demonstration purposes only. + +1. To install catalogd, navigate to the [releases](https://github.com/operator-framework/catalogd/releases/) page, and follow the install instructions included in the release you want to install. + +1. Create a `ClusterCatalog` object that points to the OperatorHub Community catalog by running the following command: + + ```sh + $ kubectl apply -f - << EOF + apiVersion: olm.operatorframework.io/v1 + kind: ClusterCatalog + metadata: + name: operatorhubio + spec: + source: + type: Image + image: + ref: quay.io/operatorhubio/catalog:latest + EOF + ``` + +1. Verify the `ClusterCatalog` object was created successfully by running the following command: + + ```sh + $ kubectl describe clustercatalog/operatorhubio + ``` + + *Example output* + ```sh + Name: operatorhubio + Namespace: + Labels: olm.operatorframework.io/metadata.name=operatorhubio + Annotations: + API Version: olm.operatorframework.io/v1 + Kind: ClusterCatalog + Metadata: + Creation Timestamp: 2024-10-17T13:48:46Z + Finalizers: + olm.operatorframework.io/delete-server-cache + Generation: 1 + Resource Version: 7908 + UID: 34eeaa91-9f8e-4254-9937-0ae9d25e92df + Spec: + Availability Mode: Available + Priority: 0 + Source: + Image: + Ref: quay.io/operatorhubio/catalog:latest + Type: Image + Status: + Conditions: + Last Transition Time: 2024-10-17T13:48:59Z + Message: Successfully unpacked and stored content from resolved source + Observed Generation: 1 + Reason: Succeeded + Status: False + Type: Progressing + Last Transition Time: 2024-10-17T13:48:59Z + Message: Serving desired content from resolved source + Observed Generation: 1 + Reason: Available + Status: True + Type: Serving + Last Unpacked: 2024-10-17T13:48:58Z + Resolved Source: + Image: + Last Successful Poll Attempt: 2024-10-17T14:49:59Z + Ref: quay.io/operatorhubio/catalog@sha256:82be554b15ff246d8cc428f8d2f4cf5857c02ce3225d95d92a769ea3095e1fc7 + Type: Image + Urls: + Base: https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio + Events: + ``` + +1. Port forward the `catalogd-service` service in the `olmv1-system` namespace: + ```sh + $ kubectl -n olmv1-system port-forward svc/catalogd-service 8080:443 + ``` + +1. Access the `v1/all` service endpoint and filter the results to a list of packages by running the following command: + + ```sh + $ curl https://localhost:8080/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.package") | .name' + ``` + + *Example output* + ```sh + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 110M 100 110M 0 0 112M 0 --:--:-- --:--:-- --:--:-- 112M + "ack-acm-controller" + "ack-apigatewayv2-controller" + "ack-applicationautoscaling-controller" + "ack-cloudtrail-controller" + "ack-cloudwatch-controller" + "ack-dynamodb-controller" + "ack-ec2-controller" + "ack-ecr-controller" + "ack-eks-controller" + "ack-elasticache-controller" + "ack-emrcontainers-controller" + "ack-eventbridge-controller" + "ack-iam-controller" + "ack-kinesis-controller" + ... + ``` +1. Run the following command to get a list of channels for the `ack-acm-controller` package: + + ```sh + $ curl https://localhost:8080/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.channel") | select(.package == "ack-acm-controller") | .name' + ``` + + *Example output* + ```sh + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 110M 100 110M 0 0 115M 0 --:--:-- --:--:-- --:--:-- 116M + "alpha" + ``` + +1. Run the following command to get a list of bundles belonging to the `ack-acm-controller` package: + + ```sh + $ curl https://localhost:8080/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.bundle") | select(.package == "ack-acm-controller") | .name' + ``` + + *Example output* + ```sh + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 110M 100 110M 0 0 122M 0 --:--:-- --:--:-- --:--:-- 122M + "ack-acm-controller.v0.0.1" + "ack-acm-controller.v0.0.2" + "ack-acm-controller.v0.0.4" + "ack-acm-controller.v0.0.5" + "ack-acm-controller.v0.0.6" + "ack-acm-controller.v0.0.7" + ``` + +## Contributing +Thanks for your interest in contributing to `catalogd`! + +`catalogd` is in the very early stages of development and a more in depth contributing guide will come in the near future. + +In the meantime, it is assumed you know how to make contributions to open source projects in general and this guide will only focus on how to manually test your changes (no automated testing yet). + +If you have any questions, feel free to reach out to us on the Kubernetes Slack channel [#olm-dev](https://kubernetes.slack.com/archives/C0181L6JYQ2) or [create an issue](https://github.com/operator-framework/catalogd/issues/new) +### Testing Local Changes +**Prerequisites** +- [Install kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) + +**Test it out** + +```sh +make run +``` + +This will build a local container image for the catalogd controller, create a new KIND cluster and then deploy onto that cluster. diff --git a/catalogd/api/doc.go b/catalogd/api/doc.go new file mode 100644 index 000000000..2e2c18a58 --- /dev/null +++ b/catalogd/api/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +//go:generate apiregister-gen --input-dirs ./... -h ../../boilerplate.go.txt + +// +// +domain=operatorframework.io + +package api diff --git a/catalogd/api/v1/clustercatalog_types.go b/catalogd/api/v1/clustercatalog_types.go new file mode 100644 index 000000000..102c389cb --- /dev/null +++ b/catalogd/api/v1/clustercatalog_types.go @@ -0,0 +1,357 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// SourceType defines the type of source used for catalogs. +// +enum +type SourceType string + +// AvailabilityMode defines the availability of the catalog +type AvailabilityMode string + +const ( + SourceTypeImage SourceType = "Image" + + TypeProgressing = "Progressing" + TypeServing = "Serving" + + // Serving reasons + ReasonAvailable = "Available" + ReasonUnavailable = "Unavailable" + ReasonUserSpecifiedUnavailable = "UserSpecifiedUnavailable" + + // Progressing reasons + ReasonSucceeded = "Succeeded" + ReasonRetrying = "Retrying" + ReasonBlocked = "Blocked" + + MetadataNameLabel = "olm.operatorframework.io/metadata.name" + + AvailabilityModeAvailable AvailabilityMode = "Available" + AvailabilityModeUnavailable AvailabilityMode = "Unavailable" +) + +//+kubebuilder:object:root=true +//+kubebuilder:resource:scope=Cluster +//+kubebuilder:subresource:status +//+kubebuilder:printcolumn:name=LastUnpacked,type=date,JSONPath=`.status.lastUnpacked` +//+kubebuilder:printcolumn:name="Serving",type=string,JSONPath=`.status.conditions[?(@.type=="Serving")].status` +//+kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp` + +// ClusterCatalog enables users to make File-Based Catalog (FBC) catalog data available to the cluster. +// For more information on FBC, see https://olm.operatorframework.io/docs/reference/file-based-catalogs/#docs +type ClusterCatalog struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata"` + + // spec is the desired state of the ClusterCatalog. + // spec is required. + // The controller will work to ensure that the desired + // catalog is unpacked and served over the catalog content HTTP server. + // +kubebuilder:validation:Required + Spec ClusterCatalogSpec `json:"spec"` + + // status contains information about the state of the ClusterCatalog such as: + // - Whether or not the catalog contents are being served via the catalog content HTTP server + // - Whether or not the ClusterCatalog is progressing to a new state + // - A reference to the source from which the catalog contents were retrieved + // +optional + Status ClusterCatalogStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// ClusterCatalogList contains a list of ClusterCatalog +type ClusterCatalogList struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ListMeta `json:"metadata"` + + // items is a list of ClusterCatalogs. + // items is required. + // +kubebuilder:validation:Required + Items []ClusterCatalog `json:"items"` +} + +// ClusterCatalogSpec defines the desired state of ClusterCatalog +type ClusterCatalogSpec struct { + // source allows a user to define the source of a catalog. + // A "catalog" contains information on content that can be installed on a cluster. + // Providing a catalog source makes the contents of the catalog discoverable and usable by + // other on-cluster components. + // These on-cluster components may do a variety of things with this information, such as + // presenting the content in a GUI dashboard or installing content from the catalog on the cluster. + // The catalog source must contain catalog metadata in the File-Based Catalog (FBC) format. + // For more information on FBC, see https://olm.operatorframework.io/docs/reference/file-based-catalogs/#docs. + // source is a required field. + // + // Below is a minimal example of a ClusterCatalogSpec that sources a catalog from an image: + // + // source: + // type: Image + // image: + // ref: quay.io/operatorhubio/catalog:latest + // + // +kubebuilder:validation:Required + Source CatalogSource `json:"source"` + + // priority allows the user to define a priority for a ClusterCatalog. + // priority is optional. + // + // A ClusterCatalog's priority is used by clients as a tie-breaker between ClusterCatalogs that meet the client's requirements. + // A higher number means higher priority. + // + // It is up to clients to decide how to handle scenarios where multiple ClusterCatalogs with the same priority meet their requirements. + // When deciding how to break the tie in this scenario, it is recommended that clients prompt their users for additional input. + // + // When omitted, the default priority is 0 because that is the zero value of integers. + // + // Negative numbers can be used to specify a priority lower than the default. + // Positive numbers can be used to specify a priority higher than the default. + // + // The lowest possible value is -2147483648. + // The highest possible value is 2147483647. + // + // +kubebuilder:default:=0 + // +kubebuilder:validation:minimum:=-2147483648 + // +kubebuilder:validation:maximum:=2147483647 + // +optional + Priority int32 `json:"priority"` + + // availabilityMode allows users to define how the ClusterCatalog is made available to clients on the cluster. + // availabilityMode is optional. + // + // Allowed values are "Available" and "Unavailable" and omitted. + // + // When omitted, the default value is "Available". + // + // When set to "Available", the catalog contents will be unpacked and served over the catalog content HTTP server. + // Setting the availabilityMode to "Available" tells clients that they should consider this ClusterCatalog + // and its contents as usable. + // + // When set to "Unavailable", the catalog contents will no longer be served over the catalog content HTTP server. + // When set to this availabilityMode it should be interpreted the same as the ClusterCatalog not existing. + // Setting the availabilityMode to "Unavailable" can be useful in scenarios where a user may not want + // to delete the ClusterCatalog all together, but would still like it to be treated as if it doesn't exist. + // + // +kubebuilder:validation:Enum:="Unavailable";"Available" + // +kubebuilder:default:="Available" + // +optional + AvailabilityMode AvailabilityMode `json:"availabilityMode,omitempty"` +} + +// ClusterCatalogStatus defines the observed state of ClusterCatalog +type ClusterCatalogStatus struct { + // conditions is a representation of the current state for this ClusterCatalog. + // + // The current condition types are Serving and Progressing. + // + // The Serving condition is used to represent whether or not the contents of the catalog is being served via the HTTP(S) web server. + // When it has a status of True and a reason of Available, the contents of the catalog are being served. + // When it has a status of False and a reason of Unavailable, the contents of the catalog are not being served because the contents are not yet available. + // When it has a status of False and a reason of UserSpecifiedUnavailable, the contents of the catalog are not being served because the catalog has been intentionally marked as unavailable. + // + // The Progressing condition is used to represent whether or not the ClusterCatalog is progressing or is ready to progress towards a new state. + // When it has a status of True and a reason of Retrying, there was an error in the progression of the ClusterCatalog that may be resolved on subsequent reconciliation attempts. + // When it has a status of True and a reason of Succeeded, the ClusterCatalog has successfully progressed to a new state and is ready to continue progressing. + // When it has a status of False and a reason of Blocked, there was an error in the progression of the ClusterCatalog that requires manual intervention for recovery. + // + // In the case that the Serving condition is True with reason Available and Progressing is True with reason Retrying, the previously fetched + // catalog contents are still being served via the HTTP(S) web server while we are progressing towards serving a new version of the catalog + // contents. This could occur when we've initially fetched the latest contents from the source for this catalog and when polling for changes + // to the contents we identify that there are updates to the contents. + // + // +listType=map + // +listMapKey=type + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` + // resolvedSource contains information about the resolved source based on the source type. + // +optional + ResolvedSource *ResolvedCatalogSource `json:"resolvedSource,omitempty"` + // urls contains the URLs that can be used to access the catalog. + // +optional + URLs *ClusterCatalogURLs `json:"urls,omitempty"` + // lastUnpacked represents the last time the contents of the + // catalog were extracted from their source format. As an example, + // when using an Image source, the OCI image will be pulled and the + // image layers written to a file-system backed cache. We refer to the + // act of this extraction from the source format as "unpacking". + // +optional + LastUnpacked *metav1.Time `json:"lastUnpacked,omitempty"` +} + +// ClusterCatalogURLs contains the URLs that can be used to access the catalog. +type ClusterCatalogURLs struct { + // base is a cluster-internal URL that provides endpoints for + // accessing the content of the catalog. + // + // It is expected that clients append the path for the endpoint they wish + // to access. + // + // Currently, only a single endpoint is served and is accessible at the path + // /api/v1. + // + // The endpoints served for the v1 API are: + // - /all - this endpoint returns the entirety of the catalog contents in the FBC format + // + // As the needs of users and clients of the evolve, new endpoints may be added. + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MaxLength:=525 + // +kubebuilder:validation:XValidation:rule="isURL(self)",message="must be a valid URL" + // +kubebuilder:validation:XValidation:rule="isURL(self) ? (url(self).getScheme() == \"http\" || url(self).getScheme() == \"https\") : true",message="scheme must be either http or https" + Base string `json:"base"` +} + +// CatalogSource is a discriminated union of possible sources for a Catalog. +// CatalogSource contains the sourcing information for a Catalog +// +union +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'Image' ? has(self.image) : !has(self.image)",message="image is required when source type is Image, and forbidden otherwise" +type CatalogSource struct { + // type is a reference to the type of source the catalog is sourced from. + // type is required. + // + // The only allowed value is "Image". + // + // When set to "Image", the ClusterCatalog content will be sourced from an OCI image. + // When using an image source, the image field must be set and must be the only field defined for this type. + // + // +unionDiscriminator + // +kubebuilder:validation:Enum:="Image" + // +kubebuilder:validation:Required + Type SourceType `json:"type"` + // image is used to configure how catalog contents are sourced from an OCI image. + // This field is required when type is Image, and forbidden otherwise. + // +optional + Image *ImageSource `json:"image,omitempty"` +} + +// ResolvedCatalogSource is a discriminated union of resolution information for a Catalog. +// ResolvedCatalogSource contains the information about a sourced Catalog +// +union +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'Image' ? has(self.image) : !has(self.image)",message="image is required when source type is Image, and forbidden otherwise" +type ResolvedCatalogSource struct { + // type is a reference to the type of source the catalog is sourced from. + // type is required. + // + // The only allowed value is "Image". + // + // When set to "Image", information about the resolved image source will be set in the 'image' field. + // + // +unionDiscriminator + // +kubebuilder:validation:Enum:="Image" + // +kubebuilder:validation:Required + Type SourceType `json:"type"` + // image is a field containing resolution information for a catalog sourced from an image. + // This field must be set when type is Image, and forbidden otherwise. + Image *ResolvedImageSource `json:"image"` +} + +// ResolvedImageSource provides information about the resolved source of a Catalog sourced from an image. +type ResolvedImageSource struct { + // ref contains the resolved image digest-based reference. + // The digest format is used so users can use other tooling to fetch the exact + // OCI manifests that were used to extract the catalog contents. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MaxLength:=1000 + // +kubebuilder:validation:XValidation:rule="self.matches('^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])((\\\\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(:[0-9]+)?\\\\b')",message="must start with a valid domain. valid domains must be alphanumeric characters (lowercase and uppercase) separated by the \".\" character." + // +kubebuilder:validation:XValidation:rule="self.find('(\\\\/[a-z0-9]+((([._]|__|[-]*)[a-z0-9]+)+)?((\\\\/[a-z0-9]+((([._]|__|[-]*)[a-z0-9]+)+)?)+)?)') != \"\"",message="a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters." + // +kubebuilder:validation:XValidation:rule="self.find('(@.*:)') != \"\"",message="must end with a digest" + // +kubebuilder:validation:XValidation:rule="self.find('(@.*:)') != \"\" ? self.find('(@.*:)').matches('(@[A-Za-z][A-Za-z0-9]*([-_+.][A-Za-z][A-Za-z0-9]*)*[:])') : true",message="digest algorithm is not valid. valid algorithms must start with an uppercase or lowercase alpha character followed by alphanumeric characters and may contain the \"-\", \"_\", \"+\", and \".\" characters." + // +kubebuilder:validation:XValidation:rule="self.find('(@.*:)') != \"\" ? self.find(':.*$').substring(1).size() >= 32 : true",message="digest is not valid. the encoded string must be at least 32 characters" + // +kubebuilder:validation:XValidation:rule="self.find('(@.*:)') != \"\" ? self.find(':.*$').matches(':[0-9A-Fa-f]*$') : true",message="digest is not valid. the encoded string must only contain hex characters (A-F, a-f, 0-9)" + Ref string `json:"ref"` +} + +// ImageSource enables users to define the information required for sourcing a Catalog from an OCI image +// +// If we see that there is a possibly valid digest-based image reference AND pollIntervalMinutes is specified, +// reject the resource since there is no use in polling a digest-based image reference. +// +kubebuilder:validation:XValidation:rule="self.ref.find('(@.*:)') != \"\" ? !has(self.pollIntervalMinutes) : true",message="cannot specify pollIntervalMinutes while using digest-based image" +type ImageSource struct { + // ref allows users to define the reference to a container image containing Catalog contents. + // ref is required. + // ref can not be more than 1000 characters. + // + // A reference can be broken down into 3 parts - the domain, name, and identifier. + // + // The domain is typically the registry where an image is located. + // It must be alphanumeric characters (lowercase and uppercase) separated by the "." character. + // Hyphenation is allowed, but the domain must start and end with alphanumeric characters. + // Specifying a port to use is also allowed by adding the ":" character followed by numeric values. + // The port must be the last value in the domain. + // Some examples of valid domain values are "registry.mydomain.io", "quay.io", "my-registry.io:8080". + // + // The name is typically the repository in the registry where an image is located. + // It must contain lowercase alphanumeric characters separated only by the ".", "_", "__", "-" characters. + // Multiple names can be concatenated with the "/" character. + // The domain and name are combined using the "/" character. + // Some examples of valid name values are "operatorhubio/catalog", "catalog", "my-catalog.prod". + // An example of the domain and name parts of a reference being combined is "quay.io/operatorhubio/catalog". + // + // The identifier is typically the tag or digest for an image reference and is present at the end of the reference. + // It starts with a separator character used to distinguish the end of the name and beginning of the identifier. + // For a digest-based reference, the "@" character is the separator. + // For a tag-based reference, the ":" character is the separator. + // An identifier is required in the reference. + // + // Digest-based references must contain an algorithm reference immediately after the "@" separator. + // The algorithm reference must be followed by the ":" character and an encoded string. + // The algorithm must start with an uppercase or lowercase alpha character followed by alphanumeric characters and may contain the "-", "_", "+", and "." characters. + // Some examples of valid algorithm values are "sha256", "sha256+b64u", "multihash+base58". + // The encoded string following the algorithm must be hex digits (a-f, A-F, 0-9) and must be a minimum of 32 characters. + // + // Tag-based references must begin with a word character (alphanumeric + "_") followed by word characters or ".", and "-" characters. + // The tag must not be longer than 127 characters. + // + // An example of a valid digest-based image reference is "quay.io/operatorhubio/catalog@sha256:200d4ddb2a73594b91358fe6397424e975205bfbe44614f5846033cad64b3f05" + // An example of a valid tag-based image reference is "quay.io/operatorhubio/catalog:latest" + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MaxLength:=1000 + // +kubebuilder:validation:XValidation:rule="self.matches('^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])((\\\\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(:[0-9]+)?\\\\b')",message="must start with a valid domain. valid domains must be alphanumeric characters (lowercase and uppercase) separated by the \".\" character." + // +kubebuilder:validation:XValidation:rule="self.find('(\\\\/[a-z0-9]+((([._]|__|[-]*)[a-z0-9]+)+)?((\\\\/[a-z0-9]+((([._]|__|[-]*)[a-z0-9]+)+)?)+)?)') != \"\"",message="a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters." + // +kubebuilder:validation:XValidation:rule="self.find('(@.*:)') != \"\" || self.find(':.*$') != \"\"",message="must end with a digest or a tag" + // +kubebuilder:validation:XValidation:rule="self.find('(@.*:)') == \"\" ? (self.find(':.*$') != \"\" ? self.find(':.*$').substring(1).size() <= 127 : true) : true",message="tag is invalid. the tag must not be more than 127 characters" + // +kubebuilder:validation:XValidation:rule="self.find('(@.*:)') == \"\" ? (self.find(':.*$') != \"\" ? self.find(':.*$').matches(':[\\\\w][\\\\w.-]*$') : true) : true",message="tag is invalid. valid tags must begin with a word character (alphanumeric + \"_\") followed by word characters or \".\", and \"-\" characters" + // +kubebuilder:validation:XValidation:rule="self.find('(@.*:)') != \"\" ? self.find('(@.*:)').matches('(@[A-Za-z][A-Za-z0-9]*([-_+.][A-Za-z][A-Za-z0-9]*)*[:])') : true",message="digest algorithm is not valid. valid algorithms must start with an uppercase or lowercase alpha character followed by alphanumeric characters and may contain the \"-\", \"_\", \"+\", and \".\" characters." + // +kubebuilder:validation:XValidation:rule="self.find('(@.*:)') != \"\" ? self.find(':.*$').substring(1).size() >= 32 : true",message="digest is not valid. the encoded string must be at least 32 characters" + // +kubebuilder:validation:XValidation:rule="self.find('(@.*:)') != \"\" ? self.find(':.*$').matches(':[0-9A-Fa-f]*$') : true",message="digest is not valid. the encoded string must only contain hex characters (A-F, a-f, 0-9)" + Ref string `json:"ref"` + + // pollIntervalMinutes allows the user to set the interval, in minutes, at which the image source should be polled for new content. + // pollIntervalMinutes is optional. + // pollIntervalMinutes can not be specified when ref is a digest-based reference. + // + // When omitted, the image will not be polled for new content. + // +kubebuilder:validation:Minimum:=1 + // +optional + PollIntervalMinutes *int `json:"pollIntervalMinutes,omitempty"` +} + +func init() { + SchemeBuilder.Register(&ClusterCatalog{}, &ClusterCatalogList{}) +} diff --git a/catalogd/api/v1/clustercatalog_types_test.go b/catalogd/api/v1/clustercatalog_types_test.go new file mode 100644 index 000000000..074acc524 --- /dev/null +++ b/catalogd/api/v1/clustercatalog_types_test.go @@ -0,0 +1,452 @@ +package v1 + +import ( + "context" + "fmt" + "os" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apiextensions-apiserver/pkg/apiserver/schema" + "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + celconfig "k8s.io/apiserver/pkg/apis/cel" + "k8s.io/utils/ptr" + "sigs.k8s.io/yaml" +) + +const crdFilePath = "../../config/base/crd/bases/olm.operatorframework.io_clustercatalogs.yaml" + +func TestImageSourceCELValidationRules(t *testing.T) { + validators := fieldValidatorsFromFile(t, crdFilePath) + pth := "openAPIV3Schema.properties.spec.properties.source.properties.image" + validator, found := validators[GroupVersion.Version][pth] + require.True(t, found) + + for name, tc := range map[string]struct { + spec ImageSource + wantErrs []string + }{ + "valid digest based image ref, poll interval not allowed, poll interval specified": { + spec: ImageSource{ + Ref: "docker.io/test-image@sha256:abcdef123456789abcdef123456789abc", + PollIntervalMinutes: ptr.To(1), + }, + wantErrs: []string{ + "openAPIV3Schema.properties.spec.properties.source.properties.image: Invalid value: \"object\": cannot specify pollIntervalMinutes while using digest-based image", + }, + }, + "valid digest based image ref, poll interval not allowed, poll interval not specified": { + spec: ImageSource{ + Ref: "docker.io/test-image@sha256:abcdef123456789abcdef123456789abc", + }, + wantErrs: []string{}, + }, + "invalid digest based image ref, invalid domain": { + spec: ImageSource{ + Ref: "-quay+docker/foo/bar@sha256:abcdef123456789abcdef123456789abc", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": must start with a valid domain. valid domains must be alphanumeric characters (lowercase and uppercase) separated by the \".\" character.", + }, + }, + "invalid digest based image ref, invalid name": { + spec: ImageSource{ + Ref: "docker.io/FOO/BAR@sha256:abcdef123456789abcdef123456789abc", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.", + }, + }, + "invalid digest based image ref, invalid digest algorithm": { + spec: ImageSource{ + Ref: "docker.io/foo/bar@99-problems:abcdef123456789abcdef123456789abc", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": digest algorithm is not valid. valid algorithms must start with an uppercase or lowercase alpha character followed by alphanumeric characters and may contain the \"-\", \"_\", \"+\", and \".\" characters.", + }, + }, + "invalid digest based image ref, too short digest encoding": { + spec: ImageSource{ + Ref: "docker.io/foo/bar@sha256:abcdef123456789", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": digest is not valid. the encoded string must be at least 32 characters", + }, + }, + "invalid digest based image ref, invalid characters in digest encoding": { + spec: ImageSource{ + Ref: "docker.io/foo/bar@sha256:XYZxy123456789abcdef123456789abc", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": digest is not valid. the encoded string must only contain hex characters (A-F, a-f, 0-9)", + }, + }, + "invalid image ref, no tag or digest": { + spec: ImageSource{ + Ref: "docker.io/foo/bar", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": must end with a digest or a tag", + }, + }, + "invalid tag based image ref, tag too long": { + spec: ImageSource{ + Ref: fmt.Sprintf("docker.io/foo/bar:%s", strings.Repeat("x", 128)), + }, + wantErrs: []string{ + "openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": tag is invalid. the tag must not be more than 127 characters", + }, + }, + "invalid tag based image ref, tag contains invalid characters": { + spec: ImageSource{ + Ref: "docker.io/foo/bar:-foo_bar-", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": tag is invalid. valid tags must begin with a word character (alphanumeric + \"_\") followed by word characters or \".\", and \"-\" characters", + }, + }, + "valid tag based image ref": { + spec: ImageSource{ + Ref: "docker.io/foo/bar:v1.0.0", + }, + wantErrs: []string{}, + }, + "valid tag based image ref, pollIntervalMinutes specified": { + spec: ImageSource{ + Ref: "docker.io/foo/bar:v1.0.0", + PollIntervalMinutes: ptr.To(5), + }, + wantErrs: []string{}, + }, + "invalid image ref, only domain with port": { + spec: ImageSource{ + Ref: "docker.io:8080", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.", + }, + }, + "valid image ref, domain with port": { + spec: ImageSource{ + Ref: "my-subdomain.docker.io:8080/foo/bar:latest", + }, + wantErrs: []string{}, + }, + "valid image ref, tag ends with hyphen": { + spec: ImageSource{ + Ref: "my-subdomain.docker.io:8080/foo/bar:latest-", + }, + wantErrs: []string{}, + }, + } { + t.Run(name, func(t *testing.T) { + obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tc.spec) //nolint:gosec + require.NoError(t, err) + errs := validator(obj, nil) + require.Equal(t, len(tc.wantErrs), len(errs), "want", tc.wantErrs, "got", errs) + for i := range tc.wantErrs { + got := errs[i].Error() + assert.Equal(t, tc.wantErrs[i], got) + } + }) + } +} + +func TestResolvedImageSourceCELValidation(t *testing.T) { + validators := fieldValidatorsFromFile(t, crdFilePath) + pth := "openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref" + validator, found := validators[GroupVersion.Version][pth] + require.True(t, found) + + for name, tc := range map[string]struct { + spec ImageSource + wantErrs []string + }{ + "valid digest based image ref": { + spec: ImageSource{ + Ref: "docker.io/test-image@sha256:abcdef123456789abcdef123456789abc", + }, + wantErrs: []string{}, + }, + "invalid digest based image ref, invalid domain": { + spec: ImageSource{ + Ref: "-quay+docker/foo/bar@sha256:abcdef123456789abcdef123456789abc", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": must start with a valid domain. valid domains must be alphanumeric characters (lowercase and uppercase) separated by the \".\" character.", + }, + }, + "invalid digest based image ref, invalid name": { + spec: ImageSource{ + Ref: "docker.io/FOO/BAR@sha256:abcdef123456789abcdef123456789abc", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.", + }, + }, + "invalid digest based image ref, invalid digest algorithm": { + spec: ImageSource{ + Ref: "docker.io/foo/bar@99-problems:abcdef123456789abcdef123456789abc", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": digest algorithm is not valid. valid algorithms must start with an uppercase or lowercase alpha character followed by alphanumeric characters and may contain the \"-\", \"_\", \"+\", and \".\" characters.", + }, + }, + "invalid digest based image ref, too short digest encoding": { + spec: ImageSource{ + Ref: "docker.io/foo/bar@sha256:abcdef123456789", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": digest is not valid. the encoded string must be at least 32 characters", + }, + }, + "invalid digest based image ref, invalid characters in digest encoding": { + spec: ImageSource{ + Ref: "docker.io/foo/bar@sha256:XYZxy123456789abcdef123456789abc", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": digest is not valid. the encoded string must only contain hex characters (A-F, a-f, 0-9)", + }, + }, + "invalid image ref, no digest": { + spec: ImageSource{ + Ref: "docker.io/foo/bar", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": must end with a digest", + }, + }, + "invalid image ref, only domain with port": { + spec: ImageSource{ + Ref: "docker.io:8080", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.", + "openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": must end with a digest", + }, + }, + "invalid image ref, tag-based ref": { + spec: ImageSource{ + Ref: "docker.io/foo/bar:latest", + }, + wantErrs: []string{ + "openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": must end with a digest", + }, + }, + } { + t.Run(name, func(t *testing.T) { + errs := validator(tc.spec.Ref, nil) + require.Equal(t, len(tc.wantErrs), len(errs), "want", tc.wantErrs, "got", errs) + for i := range tc.wantErrs { + got := errs[i].Error() + assert.Equal(t, tc.wantErrs[i], got) + } + }) + } +} + +func TestClusterCatalogURLsCELValidation(t *testing.T) { + validators := fieldValidatorsFromFile(t, crdFilePath) + pth := "openAPIV3Schema.properties.status.properties.urls.properties.base" + validator, found := validators[GroupVersion.Version][pth] + require.True(t, found) + for name, tc := range map[string]struct { + urls ClusterCatalogURLs + wantErrs []string + }{ + "base is valid": { + urls: ClusterCatalogURLs{ + Base: "https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio", + }, + wantErrs: []string{}, + }, + "base is invalid, scheme is not one of http or https": { + urls: ClusterCatalogURLs{ + Base: "file://somefilepath", + }, + wantErrs: []string{ + fmt.Sprintf("%s: Invalid value: \"string\": scheme must be either http or https", pth), + }, + }, + "base is invalid": { + urls: ClusterCatalogURLs{ + Base: "notevenarealURL", + }, + wantErrs: []string{ + fmt.Sprintf("%s: Invalid value: \"string\": must be a valid URL", pth), + }, + }, + } { + t.Run(name, func(t *testing.T) { + errs := validator(tc.urls.Base, nil) + fmt.Println(errs) + require.Equal(t, len(tc.wantErrs), len(errs)) + for i := range tc.wantErrs { + got := errs[i].Error() + assert.Equal(t, tc.wantErrs[i], got) + } + }) + } +} + +func TestSourceCELValidation(t *testing.T) { + validators := fieldValidatorsFromFile(t, crdFilePath) + pth := "openAPIV3Schema.properties.spec.properties.source" + validator, found := validators[GroupVersion.Version][pth] + require.True(t, found) + for name, tc := range map[string]struct { + source CatalogSource + wantErrs []string + }{ + "image source missing required image field": { + source: CatalogSource{ + Type: SourceTypeImage, + }, + wantErrs: []string{ + fmt.Sprintf("%s: Invalid value: \"object\": image is required when source type is %s, and forbidden otherwise", pth, SourceTypeImage), + }, + }, + "image source with required image field": { + source: CatalogSource{ + Type: SourceTypeImage, + Image: &ImageSource{ + Ref: "docker.io/foo/bar:latest", + }, + }, + wantErrs: []string{}, + }, + } { + t.Run(name, func(t *testing.T) { + obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tc.source) //nolint:gosec + require.NoError(t, err) + errs := validator(obj, nil) + fmt.Println(errs) + require.Equal(t, len(tc.wantErrs), len(errs)) + for i := range tc.wantErrs { + got := errs[i].Error() + assert.Equal(t, tc.wantErrs[i], got) + } + }) + } +} + +func TestResolvedSourceCELValidation(t *testing.T) { + validators := fieldValidatorsFromFile(t, crdFilePath) + pth := "openAPIV3Schema.properties.status.properties.resolvedSource" + validator, found := validators[GroupVersion.Version][pth] + + require.True(t, found) + for name, tc := range map[string]struct { + source ResolvedCatalogSource + wantErrs []string + }{ + "image source missing required image field": { + source: ResolvedCatalogSource{ + Type: SourceTypeImage, + }, + wantErrs: []string{ + fmt.Sprintf("%s: Invalid value: \"object\": image is required when source type is %s, and forbidden otherwise", pth, SourceTypeImage), + }, + }, + "image source with required image field": { + source: ResolvedCatalogSource{ + Type: SourceTypeImage, + Image: &ResolvedImageSource{ + Ref: "docker.io/foo/bar@sha256:abcdef123456789abcdef123456789abc", + }, + }, + wantErrs: []string{}, + }, + } { + t.Run(name, func(t *testing.T) { + obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tc.source) //nolint:gosec + require.NoError(t, err) + errs := validator(obj, nil) + require.Equal(t, len(tc.wantErrs), len(errs)) + for i := range tc.wantErrs { + got := errs[i].Error() + assert.Equal(t, tc.wantErrs[i], got) + } + }) + } +} + +// fieldValidatorsFromFile extracts the CEL validators by version and JSONPath from a CRD file and returns +// a validator func for testing against samples. +// nolint:unparam +func fieldValidatorsFromFile(t *testing.T, crdFilePath string) map[string]map[string]CELValidateFunc { + data, err := os.ReadFile(crdFilePath) + require.NoError(t, err) + + var crd apiextensionsv1.CustomResourceDefinition + err = yaml.Unmarshal(data, &crd) + require.NoError(t, err) + + ret := map[string]map[string]CELValidateFunc{} + for _, v := range crd.Spec.Versions { + var internalSchema apiextensions.JSONSchemaProps + err := apiextensionsv1.Convert_v1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(v.Schema.OpenAPIV3Schema, &internalSchema, nil) + require.NoError(t, err, "failed to convert JSONSchemaProps for version %s: %v", v.Name, err) + structuralSchema, err := schema.NewStructural(&internalSchema) + require.NoError(t, err, "failed to create StructuralSchema for version %s: %v", v.Name, err) + + versionVals, err := findCEL(structuralSchema, true, field.NewPath("openAPIV3Schema")) + require.NoError(t, err, "failed to find CEL for version %s: %v", v.Name, err) + ret[v.Name] = versionVals + } + return ret +} + +// CELValidateFunc tests a sample object against a CEL validator. +type CELValidateFunc func(obj, old interface{}) field.ErrorList + +func findCEL(s *schema.Structural, root bool, pth *field.Path) (map[string]CELValidateFunc, error) { + ret := map[string]CELValidateFunc{} + + if len(s.XValidations) > 0 { + s := *s + pth := *pth + ret[pth.String()] = func(obj, old interface{}) field.ErrorList { + errs, _ := cel.NewValidator(&s, root, celconfig.PerCallLimit).Validate(context.TODO(), &pth, &s, obj, old, celconfig.RuntimeCELCostBudget) + return errs + } + } + + for k, v := range s.Properties { + v := v + sub, err := findCEL(&v, false, pth.Child("properties").Child(k)) + if err != nil { + return nil, err + } + + for pth, val := range sub { + ret[pth] = val + } + } + if s.Items != nil { + sub, err := findCEL(s.Items, false, pth.Child("items")) + if err != nil { + return nil, err + } + for pth, val := range sub { + ret[pth] = val + } + } + if s.AdditionalProperties != nil && s.AdditionalProperties.Structural != nil { + sub, err := findCEL(s.AdditionalProperties.Structural, false, pth.Child("additionalProperties")) + if err != nil { + return nil, err + } + for pth, val := range sub { + ret[pth] = val + } + } + + return ret, nil +} diff --git a/catalogd/api/v1/groupversion_info.go b/catalogd/api/v1/groupversion_info.go new file mode 100644 index 000000000..adb650eb2 --- /dev/null +++ b/catalogd/api/v1/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1 contains API Schema definitions for the core v1 API group +// +kubebuilder:object:generate=true +// +groupName=olm.operatorframework.io +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "olm.operatorframework.io", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/catalogd/api/v1/zz_generated.deepcopy.go b/catalogd/api/v1/zz_generated.deepcopy.go new file mode 100644 index 000000000..ce4237514 --- /dev/null +++ b/catalogd/api/v1/zz_generated.deepcopy.go @@ -0,0 +1,227 @@ +//go:build !ignore_autogenerated + +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CatalogSource) DeepCopyInto(out *CatalogSource) { + *out = *in + if in.Image != nil { + in, out := &in.Image, &out.Image + *out = new(ImageSource) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogSource. +func (in *CatalogSource) DeepCopy() *CatalogSource { + if in == nil { + return nil + } + out := new(CatalogSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterCatalog) DeepCopyInto(out *ClusterCatalog) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCatalog. +func (in *ClusterCatalog) DeepCopy() *ClusterCatalog { + if in == nil { + return nil + } + out := new(ClusterCatalog) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterCatalog) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterCatalogList) DeepCopyInto(out *ClusterCatalogList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterCatalog, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCatalogList. +func (in *ClusterCatalogList) DeepCopy() *ClusterCatalogList { + if in == nil { + return nil + } + out := new(ClusterCatalogList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterCatalogList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterCatalogSpec) DeepCopyInto(out *ClusterCatalogSpec) { + *out = *in + in.Source.DeepCopyInto(&out.Source) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCatalogSpec. +func (in *ClusterCatalogSpec) DeepCopy() *ClusterCatalogSpec { + if in == nil { + return nil + } + out := new(ClusterCatalogSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterCatalogStatus) DeepCopyInto(out *ClusterCatalogStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ResolvedSource != nil { + in, out := &in.ResolvedSource, &out.ResolvedSource + *out = new(ResolvedCatalogSource) + (*in).DeepCopyInto(*out) + } + if in.URLs != nil { + in, out := &in.URLs, &out.URLs + *out = new(ClusterCatalogURLs) + **out = **in + } + if in.LastUnpacked != nil { + in, out := &in.LastUnpacked, &out.LastUnpacked + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCatalogStatus. +func (in *ClusterCatalogStatus) DeepCopy() *ClusterCatalogStatus { + if in == nil { + return nil + } + out := new(ClusterCatalogStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterCatalogURLs) DeepCopyInto(out *ClusterCatalogURLs) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCatalogURLs. +func (in *ClusterCatalogURLs) DeepCopy() *ClusterCatalogURLs { + if in == nil { + return nil + } + out := new(ClusterCatalogURLs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageSource) DeepCopyInto(out *ImageSource) { + *out = *in + if in.PollIntervalMinutes != nil { + in, out := &in.PollIntervalMinutes, &out.PollIntervalMinutes + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageSource. +func (in *ImageSource) DeepCopy() *ImageSource { + if in == nil { + return nil + } + out := new(ImageSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResolvedCatalogSource) DeepCopyInto(out *ResolvedCatalogSource) { + *out = *in + if in.Image != nil { + in, out := &in.Image, &out.Image + *out = new(ResolvedImageSource) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResolvedCatalogSource. +func (in *ResolvedCatalogSource) DeepCopy() *ResolvedCatalogSource { + if in == nil { + return nil + } + out := new(ResolvedCatalogSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResolvedImageSource) DeepCopyInto(out *ResolvedImageSource) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResolvedImageSource. +func (in *ResolvedImageSource) DeepCopy() *ResolvedImageSource { + if in == nil { + return nil + } + out := new(ResolvedImageSource) + in.DeepCopyInto(out) + return out +} diff --git a/catalogd/cmd/catalogd/main.go b/catalogd/cmd/catalogd/main.go new file mode 100644 index 000000000..77698444c --- /dev/null +++ b/catalogd/cmd/catalogd/main.go @@ -0,0 +1,387 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "crypto/tls" + "flag" + "fmt" + "log" + "net/url" + "os" + "path/filepath" + "strings" + "time" + + "github.com/containers/image/v5/types" + "github.com/go-logr/logr" + "github.com/spf13/pflag" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/fields" + k8slabels "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + k8stypes "k8s.io/apimachinery/pkg/types" + apimachineryrand "k8s.io/apimachinery/pkg/util/rand" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/metadata" + _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/klog/v2" + "k8s.io/klog/v2/textlogger" + ctrl "sigs.k8s.io/controller-runtime" + crcache "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/certwatcher" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/metrics" + "sigs.k8s.io/controller-runtime/pkg/metrics/filters" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + crwebhook "sigs.k8s.io/controller-runtime/pkg/webhook" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" + corecontrollers "github.com/operator-framework/operator-controller/catalogd/internal/controllers/core" + "github.com/operator-framework/operator-controller/catalogd/internal/features" + "github.com/operator-framework/operator-controller/catalogd/internal/garbagecollection" + catalogdmetrics "github.com/operator-framework/operator-controller/catalogd/internal/metrics" + "github.com/operator-framework/operator-controller/catalogd/internal/serverutil" + "github.com/operator-framework/operator-controller/catalogd/internal/source" + "github.com/operator-framework/operator-controller/catalogd/internal/storage" + "github.com/operator-framework/operator-controller/catalogd/internal/version" + "github.com/operator-framework/operator-controller/catalogd/internal/webhook" +) + +var ( + scheme = runtime.NewScheme() + setupLog = ctrl.Log.WithName("setup") +) + +const ( + storageDir = "catalogs" + authFilePrefix = "catalogd-global-pull-secret" +) + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + + utilruntime.Must(catalogdv1.AddToScheme(scheme)) + //+kubebuilder:scaffold:scheme +} + +func main() { + var ( + metricsAddr string + enableLeaderElection bool + probeAddr string + pprofAddr string + catalogdVersion bool + systemNamespace string + catalogServerAddr string + externalAddr string + cacheDir string + gcInterval time.Duration + certFile string + keyFile string + webhookPort int + caCertDir string + globalPullSecret string + ) + flag.StringVar(&metricsAddr, "metrics-bind-address", "", "The address for the metrics endpoint. Requires tls-cert and tls-key. (Default: ':7443')") + flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.StringVar(&pprofAddr, "pprof-bind-address", "0", "The address the pprof endpoint binds to. an empty string or 0 disables pprof") + flag.BoolVar(&enableLeaderElection, "leader-elect", false, + "Enable leader election for controller manager. "+ + "Enabling this will ensure there is only one active controller manager.") + flag.StringVar(&systemNamespace, "system-namespace", "", "The namespace catalogd uses for internal state, configuration, and workloads") + flag.StringVar(&catalogServerAddr, "catalogs-server-addr", ":8443", "The address where the unpacked catalogs' content will be accessible") + flag.StringVar(&externalAddr, "external-address", "catalogd-service.olmv1-system.svc", "The external address at which the http(s) server is reachable.") + flag.StringVar(&cacheDir, "cache-dir", "/var/cache/", "The directory in the filesystem that catalogd will use for file based caching") + flag.BoolVar(&catalogdVersion, "version", false, "print the catalogd version and exit") + flag.DurationVar(&gcInterval, "gc-interval", 12*time.Hour, "interval in which garbage collection should be run against the catalog content cache") + flag.StringVar(&certFile, "tls-cert", "", "The certificate file used for serving catalog and metrics. Required to enable the metrics server. Requires tls-key.") + flag.StringVar(&keyFile, "tls-key", "", "The key file used for serving catalog contents and metrics. Required to enable the metrics server. Requires tls-cert.") + flag.IntVar(&webhookPort, "webhook-server-port", 9443, "The port that the mutating webhook server serves at.") + flag.StringVar(&caCertDir, "ca-certs-dir", "", "The directory of CA certificate to use for verifying HTTPS connections to image registries.") + flag.StringVar(&globalPullSecret, "global-pull-secret", "", "The / of the global pull secret that is going to be used to pull bundle images.") + + klog.InitFlags(flag.CommandLine) + + // Combine both flagsets and parse them + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) + features.CatalogdFeatureGate.AddFlag(pflag.CommandLine) + pflag.Parse() + + if catalogdVersion { + fmt.Printf("%#v\n", version.Version()) + os.Exit(0) + } + + ctrl.SetLogger(textlogger.NewLogger(textlogger.NewConfig())) + + authFilePath := filepath.Join(os.TempDir(), fmt.Sprintf("%s-%s.json", authFilePrefix, apimachineryrand.String(8))) + var globalPullSecretKey *k8stypes.NamespacedName + if globalPullSecret != "" { + secretParts := strings.Split(globalPullSecret, "/") + if len(secretParts) != 2 { + setupLog.Error(fmt.Errorf("incorrect number of components"), "value of global-pull-secret should be of the format /") + os.Exit(1) + } + globalPullSecretKey = &k8stypes.NamespacedName{Name: secretParts[1], Namespace: secretParts[0]} + } + + if (certFile != "" && keyFile == "") || (certFile == "" && keyFile != "") { + setupLog.Error(nil, "unable to configure TLS certificates: tls-cert and tls-key flags must be used together") + os.Exit(1) + } + + if metricsAddr != "" && certFile == "" && keyFile == "" { + setupLog.Error(nil, "metrics-bind-address requires tls-cert and tls-key flags to be set") + os.Exit(1) + } + + if certFile != "" && keyFile != "" && metricsAddr == "" { + metricsAddr = ":7443" + } + + protocol := "http://" + if certFile != "" && keyFile != "" { + protocol = "https://" + } + externalAddr = protocol + externalAddr + + cfg := ctrl.GetConfigOrDie() + + cw, err := certwatcher.New(certFile, keyFile) + if err != nil { + log.Fatalf("Failed to initialize certificate watcher: %v", err) + } + + tlsOpts := func(config *tls.Config) { + config.GetCertificate = cw.GetCertificate + // Ensure HTTP/2 is disabled by default for webhooks and metrics. + // Disabling HTTP/2 mitigates vulnerabilities associated with: + // - HTTP/2 Stream Cancellation (GHSA-qppj-fm5r-hxr3) + // - HTTP/2 Rapid Reset (GHSA-4374-p667-p6c8) + // While CVE fixes exist, they remain insufficient; disabling HTTP/2 helps reduce risks. + // For details, see: https://github.com/kubernetes/kubernetes/issues/121197 + config.NextProtos = []string{"http/1.1"} + } + + // Create webhook server and configure TLS + webhookServer := crwebhook.NewServer(crwebhook.Options{ + Port: webhookPort, + TLSOpts: []func(*tls.Config){ + tlsOpts, + }, + }) + + metricsServerOptions := metricsserver.Options{} + if len(certFile) > 0 && len(keyFile) > 0 { + setupLog.Info("Starting metrics server with TLS enabled", "addr", metricsAddr, "tls-cert", certFile, "tls-key", keyFile) + + metricsServerOptions.BindAddress = metricsAddr + metricsServerOptions.SecureServing = true + metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization + + metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, tlsOpts) + } else { + // Note that the metrics server is not serving if the BindAddress is set to "0". + // Therefore, the metrics server is disabled by default. It is only enabled + // if certFile and keyFile are provided. The intention is not allowing the metrics + // be served with the default self-signed certificate generated by controller-runtime. + metricsServerOptions.BindAddress = "0" + setupLog.Info("WARNING: Metrics Server is disabled. " + + "Metrics will not be served since the TLS certificate and key file are not provided.") + } + + cacheOptions := crcache.Options{ + ByObject: map[client.Object]crcache.ByObject{}, + } + if globalPullSecretKey != nil { + cacheOptions.ByObject[&corev1.Secret{}] = crcache.ByObject{ + Namespaces: map[string]crcache.Config{ + globalPullSecretKey.Namespace: { + LabelSelector: k8slabels.Everything(), + FieldSelector: fields.SelectorFromSet(map[string]string{ + "metadata.name": globalPullSecretKey.Name, + }), + }, + }, + } + } + + // Create manager + mgr, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: scheme, + Metrics: metricsServerOptions, + PprofBindAddress: pprofAddr, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "catalogd-operator-lock", + WebhookServer: webhookServer, + Cache: cacheOptions, + }) + if err != nil { + setupLog.Error(err, "unable to create manager") + os.Exit(1) + } + + // Add the certificate watcher to the manager + err = mgr.Add(cw) + if err != nil { + setupLog.Error(err, "unable to add certificate watcher to manager") + os.Exit(1) + } + + if systemNamespace == "" { + systemNamespace = podNamespace() + } + + if err := os.MkdirAll(cacheDir, 0700); err != nil { + setupLog.Error(err, "unable to create cache directory") + os.Exit(1) + } + + unpackCacheBasePath := filepath.Join(cacheDir, source.UnpackCacheDir) + if err := os.MkdirAll(unpackCacheBasePath, 0770); err != nil { + setupLog.Error(err, "unable to create cache directory for unpacking") + os.Exit(1) + } + unpacker := &source.ContainersImageRegistry{ + BaseCachePath: unpackCacheBasePath, + SourceContextFunc: func(logger logr.Logger) (*types.SystemContext, error) { + srcContext := &types.SystemContext{ + DockerCertPath: caCertDir, + OCICertPath: caCertDir, + } + if _, err := os.Stat(authFilePath); err == nil && globalPullSecretKey != nil { + logger.Info("using available authentication information for pulling image") + srcContext.AuthFilePath = authFilePath + } else if os.IsNotExist(err) { + logger.Info("no authentication information found for pulling image, proceeding without auth") + } else { + return nil, fmt.Errorf("could not stat auth file, error: %w", err) + } + return srcContext, nil + }, + } + + var localStorage storage.Instance + metrics.Registry.MustRegister(catalogdmetrics.RequestDurationMetric) + + storeDir := filepath.Join(cacheDir, storageDir) + if err := os.MkdirAll(storeDir, 0700); err != nil { + setupLog.Error(err, "unable to create storage directory for catalogs") + os.Exit(1) + } + + baseStorageURL, err := url.Parse(fmt.Sprintf("%s/catalogs/", externalAddr)) + if err != nil { + setupLog.Error(err, "unable to create base storage URL") + os.Exit(1) + } + + localStorage = storage.LocalDirV1{RootDir: storeDir, RootURL: baseStorageURL} + + // Config for the the catalogd web server + catalogServerConfig := serverutil.CatalogServerConfig{ + ExternalAddr: externalAddr, + CatalogAddr: catalogServerAddr, + CertFile: certFile, + KeyFile: keyFile, + LocalStorage: localStorage, + } + + err = serverutil.AddCatalogServerToManager(mgr, catalogServerConfig, cw) + if err != nil { + setupLog.Error(err, "unable to configure catalog server") + os.Exit(1) + } + + if err = (&corecontrollers.ClusterCatalogReconciler{ + Client: mgr.GetClient(), + Unpacker: unpacker, + Storage: localStorage, + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "ClusterCatalog") + os.Exit(1) + } + + if globalPullSecretKey != nil { + setupLog.Info("creating SecretSyncer controller for watching secret", "Secret", globalPullSecret) + err := (&corecontrollers.PullSecretReconciler{ + Client: mgr.GetClient(), + AuthFilePath: authFilePath, + SecretKey: *globalPullSecretKey, + }).SetupWithManager(mgr) + if err != nil { + setupLog.Error(err, "unable to create controller", "controller", "SecretSyncer") + os.Exit(1) + } + } + //+kubebuilder:scaffold:builder + + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up ready check") + os.Exit(1) + } + + metaClient, err := metadata.NewForConfig(cfg) + if err != nil { + setupLog.Error(err, "unable to setup client for garbage collection") + os.Exit(1) + } + + ctx := ctrl.SetupSignalHandler() + gc := &garbagecollection.GarbageCollector{ + CachePath: unpackCacheBasePath, + Logger: ctrl.Log.WithName("garbage-collector"), + MetadataClient: metaClient, + Interval: gcInterval, + } + if err := mgr.Add(gc); err != nil { + setupLog.Error(err, "unable to add garbage collector to manager") + os.Exit(1) + } + + // mutating webhook that labels ClusterCatalogs with name label + if err = (&webhook.ClusterCatalog{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "ClusterCatalog") + os.Exit(1) + } + + setupLog.Info("starting mutating webhook manager") + if err := mgr.Start(ctx); err != nil { + setupLog.Error(err, "problem running manager") + os.Exit(1) + } + if err := os.Remove(authFilePath); err != nil { + setupLog.Error(err, "failed to cleanup temporary auth file") + os.Exit(1) + } +} + +func podNamespace() string { + namespace, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace") + if err != nil { + return "olmv1-system" + } + return string(namespace) +} diff --git a/catalogd/config/base/crd/bases/olm.operatorframework.io_clustercatalogs.yaml b/catalogd/config/base/crd/bases/olm.operatorframework.io_clustercatalogs.yaml new file mode 100644 index 000000000..46750f058 --- /dev/null +++ b/catalogd/config/base/crd/bases/olm.operatorframework.io_clustercatalogs.yaml @@ -0,0 +1,441 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: clustercatalogs.olm.operatorframework.io +spec: + group: olm.operatorframework.io + names: + kind: ClusterCatalog + listKind: ClusterCatalogList + plural: clustercatalogs + singular: clustercatalog + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.lastUnpacked + name: LastUnpacked + type: date + - jsonPath: .status.conditions[?(@.type=="Serving")].status + name: Serving + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + ClusterCatalog enables users to make File-Based Catalog (FBC) catalog data available to the cluster. + For more information on FBC, see https://olm.operatorframework.io/docs/reference/file-based-catalogs/#docs + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + spec is the desired state of the ClusterCatalog. + spec is required. + The controller will work to ensure that the desired + catalog is unpacked and served over the catalog content HTTP server. + properties: + availabilityMode: + default: Available + description: |- + availabilityMode allows users to define how the ClusterCatalog is made available to clients on the cluster. + availabilityMode is optional. + + Allowed values are "Available" and "Unavailable" and omitted. + + When omitted, the default value is "Available". + + When set to "Available", the catalog contents will be unpacked and served over the catalog content HTTP server. + Setting the availabilityMode to "Available" tells clients that they should consider this ClusterCatalog + and its contents as usable. + + When set to "Unavailable", the catalog contents will no longer be served over the catalog content HTTP server. + When set to this availabilityMode it should be interpreted the same as the ClusterCatalog not existing. + Setting the availabilityMode to "Unavailable" can be useful in scenarios where a user may not want + to delete the ClusterCatalog all together, but would still like it to be treated as if it doesn't exist. + enum: + - Unavailable + - Available + type: string + priority: + default: 0 + description: |- + priority allows the user to define a priority for a ClusterCatalog. + priority is optional. + + A ClusterCatalog's priority is used by clients as a tie-breaker between ClusterCatalogs that meet the client's requirements. + A higher number means higher priority. + + It is up to clients to decide how to handle scenarios where multiple ClusterCatalogs with the same priority meet their requirements. + When deciding how to break the tie in this scenario, it is recommended that clients prompt their users for additional input. + + When omitted, the default priority is 0 because that is the zero value of integers. + + Negative numbers can be used to specify a priority lower than the default. + Positive numbers can be used to specify a priority higher than the default. + + The lowest possible value is -2147483648. + The highest possible value is 2147483647. + format: int32 + type: integer + source: + description: |- + source allows a user to define the source of a catalog. + A "catalog" contains information on content that can be installed on a cluster. + Providing a catalog source makes the contents of the catalog discoverable and usable by + other on-cluster components. + These on-cluster components may do a variety of things with this information, such as + presenting the content in a GUI dashboard or installing content from the catalog on the cluster. + The catalog source must contain catalog metadata in the File-Based Catalog (FBC) format. + For more information on FBC, see https://olm.operatorframework.io/docs/reference/file-based-catalogs/#docs. + source is a required field. + + Below is a minimal example of a ClusterCatalogSpec that sources a catalog from an image: + + source: + type: Image + image: + ref: quay.io/operatorhubio/catalog:latest + properties: + image: + description: |- + image is used to configure how catalog contents are sourced from an OCI image. + This field is required when type is Image, and forbidden otherwise. + properties: + pollIntervalMinutes: + description: |- + pollIntervalMinutes allows the user to set the interval, in minutes, at which the image source should be polled for new content. + pollIntervalMinutes is optional. + pollIntervalMinutes can not be specified when ref is a digest-based reference. + + When omitted, the image will not be polled for new content. + minimum: 1 + type: integer + ref: + description: |- + ref allows users to define the reference to a container image containing Catalog contents. + ref is required. + ref can not be more than 1000 characters. + + A reference can be broken down into 3 parts - the domain, name, and identifier. + + The domain is typically the registry where an image is located. + It must be alphanumeric characters (lowercase and uppercase) separated by the "." character. + Hyphenation is allowed, but the domain must start and end with alphanumeric characters. + Specifying a port to use is also allowed by adding the ":" character followed by numeric values. + The port must be the last value in the domain. + Some examples of valid domain values are "registry.mydomain.io", "quay.io", "my-registry.io:8080". + + The name is typically the repository in the registry where an image is located. + It must contain lowercase alphanumeric characters separated only by the ".", "_", "__", "-" characters. + Multiple names can be concatenated with the "/" character. + The domain and name are combined using the "/" character. + Some examples of valid name values are "operatorhubio/catalog", "catalog", "my-catalog.prod". + An example of the domain and name parts of a reference being combined is "quay.io/operatorhubio/catalog". + + The identifier is typically the tag or digest for an image reference and is present at the end of the reference. + It starts with a separator character used to distinguish the end of the name and beginning of the identifier. + For a digest-based reference, the "@" character is the separator. + For a tag-based reference, the ":" character is the separator. + An identifier is required in the reference. + + Digest-based references must contain an algorithm reference immediately after the "@" separator. + The algorithm reference must be followed by the ":" character and an encoded string. + The algorithm must start with an uppercase or lowercase alpha character followed by alphanumeric characters and may contain the "-", "_", "+", and "." characters. + Some examples of valid algorithm values are "sha256", "sha256+b64u", "multihash+base58". + The encoded string following the algorithm must be hex digits (a-f, A-F, 0-9) and must be a minimum of 32 characters. + + Tag-based references must begin with a word character (alphanumeric + "_") followed by word characters or ".", and "-" characters. + The tag must not be longer than 127 characters. + + An example of a valid digest-based image reference is "quay.io/operatorhubio/catalog@sha256:200d4ddb2a73594b91358fe6397424e975205bfbe44614f5846033cad64b3f05" + An example of a valid tag-based image reference is "quay.io/operatorhubio/catalog:latest" + maxLength: 1000 + type: string + x-kubernetes-validations: + - message: must start with a valid domain. valid domains must + be alphanumeric characters (lowercase and uppercase) separated + by the "." character. + rule: self.matches('^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])((\\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(:[0-9]+)?\\b') + - message: a valid name is required. valid names must contain + lowercase alphanumeric characters separated only by the + ".", "_", "__", "-" characters. + rule: self.find('(\\/[a-z0-9]+((([._]|__|[-]*)[a-z0-9]+)+)?((\\/[a-z0-9]+((([._]|__|[-]*)[a-z0-9]+)+)?)+)?)') + != "" + - message: must end with a digest or a tag + rule: self.find('(@.*:)') != "" || self.find(':.*$') != + "" + - message: tag is invalid. the tag must not be more than 127 + characters + rule: 'self.find(''(@.*:)'') == "" ? (self.find('':.*$'') + != "" ? self.find('':.*$'').substring(1).size() <= 127 + : true) : true' + - message: tag is invalid. valid tags must begin with a word + character (alphanumeric + "_") followed by word characters + or ".", and "-" characters + rule: 'self.find(''(@.*:)'') == "" ? (self.find('':.*$'') + != "" ? self.find('':.*$'').matches('':[\\w][\\w.-]*$'') + : true) : true' + - message: digest algorithm is not valid. valid algorithms + must start with an uppercase or lowercase alpha character + followed by alphanumeric characters and may contain the + "-", "_", "+", and "." characters. + rule: 'self.find(''(@.*:)'') != "" ? self.find(''(@.*:)'').matches(''(@[A-Za-z][A-Za-z0-9]*([-_+.][A-Za-z][A-Za-z0-9]*)*[:])'') + : true' + - message: digest is not valid. the encoded string must be + at least 32 characters + rule: 'self.find(''(@.*:)'') != "" ? self.find('':.*$'').substring(1).size() + >= 32 : true' + - message: digest is not valid. the encoded string must only + contain hex characters (A-F, a-f, 0-9) + rule: 'self.find(''(@.*:)'') != "" ? self.find('':.*$'').matches('':[0-9A-Fa-f]*$'') + : true' + required: + - ref + type: object + x-kubernetes-validations: + - message: cannot specify pollIntervalMinutes while using digest-based + image + rule: 'self.ref.find(''(@.*:)'') != "" ? !has(self.pollIntervalMinutes) + : true' + type: + description: |- + type is a reference to the type of source the catalog is sourced from. + type is required. + + The only allowed value is "Image". + + When set to "Image", the ClusterCatalog content will be sourced from an OCI image. + When using an image source, the image field must be set and must be the only field defined for this type. + enum: + - Image + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: image is required when source type is Image, and forbidden + otherwise + rule: 'has(self.type) && self.type == ''Image'' ? has(self.image) + : !has(self.image)' + required: + - source + type: object + status: + description: |- + status contains information about the state of the ClusterCatalog such as: + - Whether or not the catalog contents are being served via the catalog content HTTP server + - Whether or not the ClusterCatalog is progressing to a new state + - A reference to the source from which the catalog contents were retrieved + properties: + conditions: + description: |- + conditions is a representation of the current state for this ClusterCatalog. + + The current condition types are Serving and Progressing. + + The Serving condition is used to represent whether or not the contents of the catalog is being served via the HTTP(S) web server. + When it has a status of True and a reason of Available, the contents of the catalog are being served. + When it has a status of False and a reason of Unavailable, the contents of the catalog are not being served because the contents are not yet available. + When it has a status of False and a reason of UserSpecifiedUnavailable, the contents of the catalog are not being served because the catalog has been intentionally marked as unavailable. + + The Progressing condition is used to represent whether or not the ClusterCatalog is progressing or is ready to progress towards a new state. + When it has a status of True and a reason of Retrying, there was an error in the progression of the ClusterCatalog that may be resolved on subsequent reconciliation attempts. + When it has a status of True and a reason of Succeeded, the ClusterCatalog has successfully progressed to a new state and is ready to continue progressing. + When it has a status of False and a reason of Blocked, there was an error in the progression of the ClusterCatalog that requires manual intervention for recovery. + + In the case that the Serving condition is True with reason Available and Progressing is True with reason Retrying, the previously fetched + catalog contents are still being served via the HTTP(S) web server while we are progressing towards serving a new version of the catalog + contents. This could occur when we've initially fetched the latest contents from the source for this catalog and when polling for changes + to the contents we identify that there are updates to the contents. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastUnpacked: + description: |- + lastUnpacked represents the last time the contents of the + catalog were extracted from their source format. As an example, + when using an Image source, the OCI image will be pulled and the + image layers written to a file-system backed cache. We refer to the + act of this extraction from the source format as "unpacking". + format: date-time + type: string + resolvedSource: + description: resolvedSource contains information about the resolved + source based on the source type. + properties: + image: + description: |- + image is a field containing resolution information for a catalog sourced from an image. + This field must be set when type is Image, and forbidden otherwise. + properties: + ref: + description: |- + ref contains the resolved image digest-based reference. + The digest format is used so users can use other tooling to fetch the exact + OCI manifests that were used to extract the catalog contents. + maxLength: 1000 + type: string + x-kubernetes-validations: + - message: must start with a valid domain. valid domains must + be alphanumeric characters (lowercase and uppercase) separated + by the "." character. + rule: self.matches('^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])((\\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(:[0-9]+)?\\b') + - message: a valid name is required. valid names must contain + lowercase alphanumeric characters separated only by the + ".", "_", "__", "-" characters. + rule: self.find('(\\/[a-z0-9]+((([._]|__|[-]*)[a-z0-9]+)+)?((\\/[a-z0-9]+((([._]|__|[-]*)[a-z0-9]+)+)?)+)?)') + != "" + - message: must end with a digest + rule: self.find('(@.*:)') != "" + - message: digest algorithm is not valid. valid algorithms + must start with an uppercase or lowercase alpha character + followed by alphanumeric characters and may contain the + "-", "_", "+", and "." characters. + rule: 'self.find(''(@.*:)'') != "" ? self.find(''(@.*:)'').matches(''(@[A-Za-z][A-Za-z0-9]*([-_+.][A-Za-z][A-Za-z0-9]*)*[:])'') + : true' + - message: digest is not valid. the encoded string must be + at least 32 characters + rule: 'self.find(''(@.*:)'') != "" ? self.find('':.*$'').substring(1).size() + >= 32 : true' + - message: digest is not valid. the encoded string must only + contain hex characters (A-F, a-f, 0-9) + rule: 'self.find(''(@.*:)'') != "" ? self.find('':.*$'').matches('':[0-9A-Fa-f]*$'') + : true' + required: + - ref + type: object + type: + description: |- + type is a reference to the type of source the catalog is sourced from. + type is required. + + The only allowed value is "Image". + + When set to "Image", information about the resolved image source will be set in the 'image' field. + enum: + - Image + type: string + required: + - image + - type + type: object + x-kubernetes-validations: + - message: image is required when source type is Image, and forbidden + otherwise + rule: 'has(self.type) && self.type == ''Image'' ? has(self.image) + : !has(self.image)' + urls: + description: urls contains the URLs that can be used to access the + catalog. + properties: + base: + description: |- + base is a cluster-internal URL that provides endpoints for + accessing the content of the catalog. + + It is expected that clients append the path for the endpoint they wish + to access. + + Currently, only a single endpoint is served and is accessible at the path + /api/v1. + + The endpoints served for the v1 API are: + - /all - this endpoint returns the entirety of the catalog contents in the FBC format + + As the needs of users and clients of the evolve, new endpoints may be added. + maxLength: 525 + type: string + x-kubernetes-validations: + - message: must be a valid URL + rule: isURL(self) + - message: scheme must be either http or https + rule: 'isURL(self) ? (url(self).getScheme() == "http" || url(self).getScheme() + == "https") : true' + required: + - base + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/catalogd/config/base/crd/kustomization.yaml b/catalogd/config/base/crd/kustomization.yaml new file mode 100644 index 000000000..36c151281 --- /dev/null +++ b/catalogd/config/base/crd/kustomization.yaml @@ -0,0 +1,6 @@ +# This kustomization.yaml is not intended to be run by itself, +# since it depends on service name and namespace that are out of this kustomize package. +# It should be run by config/default +resources: +- bases/olm.operatorframework.io_clustercatalogs.yaml +#+kubebuilder:scaffold:crdkustomizeresource diff --git a/catalogd/config/base/default/clustercatalogs/default-catalogs.yaml b/catalogd/config/base/default/clustercatalogs/default-catalogs.yaml new file mode 100644 index 000000000..a656b3509 --- /dev/null +++ b/catalogd/config/base/default/clustercatalogs/default-catalogs.yaml @@ -0,0 +1,11 @@ +apiVersion: olm.operatorframework.io/v1 +kind: ClusterCatalog +metadata: + name: operatorhubio + namespace: olmv1-system +spec: + source: + type: Image + image: + ref: quay.io/operatorhubio/catalog:latest + pollIntervalMinutes: 10 diff --git a/catalogd/config/base/default/kustomization.yaml b/catalogd/config/base/default/kustomization.yaml new file mode 100644 index 000000000..93dce3bac --- /dev/null +++ b/catalogd/config/base/default/kustomization.yaml @@ -0,0 +1,17 @@ +# Adds namespace to all resources. +namespace: olmv1-system + +# Value of this field is prepended to the +# names of all resources, e.g. a deployment named +# "wordpress" becomes "alices-wordpress". +# Note that it should also match with the prefix (text before '-') of the namespace +# field above. +namePrefix: catalogd- + +# the following config is for teaching kustomize how to do var substitution +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../crd +- ../rbac +- ../manager diff --git a/catalogd/config/base/manager/catalogd_service.yaml b/catalogd/config/base/manager/catalogd_service.yaml new file mode 100644 index 000000000..693b687f3 --- /dev/null +++ b/catalogd/config/base/manager/catalogd_service.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/part-of: olm + app.kubernetes.io/name: catalogd + name: service + namespace: system +spec: + selector: + control-plane: catalogd-controller-manager + ports: + - name: http + protocol: TCP + port: 80 + targetPort: 8443 + - name: webhook + protocol: TCP + port: 9443 + targetPort: 9443 + - name: metrics + protocol: TCP + port: 7443 + targetPort: 7443 diff --git a/catalogd/config/base/manager/kustomization.yaml b/catalogd/config/base/manager/kustomization.yaml new file mode 100644 index 000000000..4ca2781d9 --- /dev/null +++ b/catalogd/config/base/manager/kustomization.yaml @@ -0,0 +1,17 @@ +resources: +- manager.yaml +- catalogd_service.yaml +- webhook/manifests.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +images: +- name: controller + newName: quay.io/operator-framework/catalogd + newTag: devel +patches: +- path: webhook/patch.yaml + target: + group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutating-webhook-configuration + version: v1 diff --git a/catalogd/config/base/manager/manager.yaml b/catalogd/config/base/manager/manager.yaml new file mode 100644 index 000000000..b394b2800 --- /dev/null +++ b/catalogd/config/base/manager/manager.yaml @@ -0,0 +1,91 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + app.kubernetes.io/part-of: olm + pod-security.kubernetes.io/enforce: baseline + pod-security.kubernetes.io/enforce-version: latest + name: system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system + annotations: + kubectl.kubernetes.io/default-logs-container: manager + labels: + control-plane: catalogd-controller-manager +spec: + selector: + matchLabels: + control-plane: catalogd-controller-manager + replicas: 1 + minReadySeconds: 5 + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + control-plane: catalogd-controller-manager + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - ppc64le + - s390x + - key: kubernetes.io/os + operator: In + values: + - linux + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - command: + - ./catalogd + args: + - --leader-elect + - --metrics-bind-address=:7443 + - --external-address=catalogd-service.olmv1-system.svc + image: controller:latest + name: manager + volumeMounts: + - name: cache + mountPath: /var/cache/ + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + requests: + cpu: 100m + memory: 200Mi + imagePullPolicy: IfNotPresent + terminationMessagePolicy: FallbackToLogsOnError + serviceAccountName: controller-manager + terminationGracePeriodSeconds: 10 + volumes: + - name: cache + emptyDir: {} diff --git a/catalogd/config/base/manager/webhook/manifests.yaml b/catalogd/config/base/manager/webhook/manifests.yaml new file mode 100644 index 000000000..a5842de42 --- /dev/null +++ b/catalogd/config/base/manager/webhook/manifests.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-olm-operatorframework-io-v1-clustercatalog + failurePolicy: Fail + name: inject-metadata-name.olm.operatorframework.io + rules: + - apiGroups: + - olm.operatorframework.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - clustercatalogs + sideEffects: None + timeoutSeconds: 10 diff --git a/catalogd/config/base/manager/webhook/patch.yaml b/catalogd/config/base/manager/webhook/patch.yaml new file mode 100644 index 000000000..ab8528c76 --- /dev/null +++ b/catalogd/config/base/manager/webhook/patch.yaml @@ -0,0 +1,20 @@ +# None of these values can be set via the kubebuilder directive, hence this patch +- op: replace + path: /webhooks/0/clientConfig/service/namespace + value: olmv1-system +- op: replace + path: /webhooks/0/clientConfig/service/name + value: catalogd-service +- op: add + path: /webhooks/0/clientConfig/service/port + value: 9443 +# Make sure there's a name defined, otherwise, we can't create a label. This could happen when generateName is set +# Then, if any of the conditions are true, create the label: +# 1. No labels exist +# 2. The olm.operatorframework.io/metadata.name label doesn't exist +# 3. The olm.operatorframework.io/metadata.name label doesn't match the name +- op: add + path: /webhooks/0/matchConditions + value: + - name: MissingOrIncorrectMetadataNameLabel + expression: "'name' in object.metadata && (!has(object.metadata.labels) || !('olm.operatorframework.io/metadata.name' in object.metadata.labels) || object.metadata.labels['olm.operatorframework.io/metadata.name'] != object.metadata.name)" diff --git a/catalogd/config/base/nginx-ingress/kustomization.yaml b/catalogd/config/base/nginx-ingress/kustomization.yaml new file mode 100644 index 000000000..7bdced5d6 --- /dev/null +++ b/catalogd/config/base/nginx-ingress/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- ../default +- resources/nginx_ingress.yaml +- https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml diff --git a/catalogd/config/base/nginx-ingress/resources/nginx_ingress.yaml b/catalogd/config/base/nginx-ingress/resources/nginx_ingress.yaml new file mode 100644 index 000000000..81f775fba --- /dev/null +++ b/catalogd/config/base/nginx-ingress/resources/nginx_ingress.yaml @@ -0,0 +1,17 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: catalogd-ingress + namespace: olmv1-system +spec: + ingressClassName: nginx + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: catalogd-service + port: + number: 80 diff --git a/catalogd/config/base/rbac/auth_proxy_client_clusterrole.yaml b/catalogd/config/base/rbac/auth_proxy_client_clusterrole.yaml new file mode 100644 index 000000000..ab8871b2e --- /dev/null +++ b/catalogd/config/base/rbac/auth_proxy_client_clusterrole.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/part-of: olm + app.kubernetes.io/name: catalogd + name: metrics-reader +rules: +- nonResourceURLs: + - "/metrics" + verbs: + - get diff --git a/catalogd/config/base/rbac/auth_proxy_role.yaml b/catalogd/config/base/rbac/auth_proxy_role.yaml new file mode 100644 index 000000000..3edf78f58 --- /dev/null +++ b/catalogd/config/base/rbac/auth_proxy_role.yaml @@ -0,0 +1,20 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/part-of: olm + app.kubernetes.io/name: catalogd + name: proxy-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/catalogd/config/base/rbac/auth_proxy_role_binding.yaml b/catalogd/config/base/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 000000000..2efcf8dd8 --- /dev/null +++ b/catalogd/config/base/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/part-of: olm + app.kubernetes.io/name: catalogd + name: proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: proxy-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/catalogd/config/base/rbac/kustomization.yaml b/catalogd/config/base/rbac/kustomization.yaml new file mode 100644 index 000000000..8ed66bdd1 --- /dev/null +++ b/catalogd/config/base/rbac/kustomization.yaml @@ -0,0 +1,20 @@ +resources: +# All RBAC will be applied under this service account in +# the deployment namespace. You may comment out this resource +# if your manager will use a service account that exists at +# runtime. Be sure to update RoleBinding and ClusterRoleBinding +# subjects if changing service account names. +- service_account.yaml +- role.yaml +- role_binding.yaml +- leader_election_role.yaml +- leader_election_role_binding.yaml +# The following RBAC configurations are used to protect +# the metrics endpoint with authn/authz. These configurations +# ensure that only authorized users and service accounts +# can access the metrics endpoint. Comment the following +# permissions if you want to disable this protection. +# More info: https://book.kubebuilder.io/reference/metrics.html +- auth_proxy_role.yaml +- auth_proxy_role_binding.yaml +- auth_proxy_client_clusterrole.yaml diff --git a/catalogd/config/base/rbac/leader_election_role.yaml b/catalogd/config/base/rbac/leader_election_role.yaml new file mode 100644 index 000000000..37564d084 --- /dev/null +++ b/catalogd/config/base/rbac/leader_election_role.yaml @@ -0,0 +1,40 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/part-of: olm + app.kubernetes.io/name: catalogd + name: leader-election-role +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/catalogd/config/base/rbac/leader_election_role_binding.yaml b/catalogd/config/base/rbac/leader_election_role_binding.yaml new file mode 100644 index 000000000..6ad0ccf99 --- /dev/null +++ b/catalogd/config/base/rbac/leader_election_role_binding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/part-of: olm + app.kubernetes.io/name: catalogd + name: leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/catalogd/config/base/rbac/role.yaml b/catalogd/config/base/rbac/role.yaml new file mode 100644 index 000000000..40f4095c6 --- /dev/null +++ b/catalogd/config/base/rbac/role.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: manager-role +rules: +- apiGroups: + - olm.operatorframework.io + resources: + - clustercatalogs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - olm.operatorframework.io + resources: + - clustercatalogs/finalizers + verbs: + - update +- apiGroups: + - olm.operatorframework.io + resources: + - clustercatalogs/status + verbs: + - get + - patch + - update diff --git a/catalogd/config/base/rbac/role_binding.yaml b/catalogd/config/base/rbac/role_binding.yaml new file mode 100644 index 000000000..a618c0e47 --- /dev/null +++ b/catalogd/config/base/rbac/role_binding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/part-of: olm + app.kubernetes.io/name: catalogd + name: manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: manager-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/catalogd/config/base/rbac/service_account.yaml b/catalogd/config/base/rbac/service_account.yaml new file mode 100644 index 000000000..3f0e7af74 --- /dev/null +++ b/catalogd/config/base/rbac/service_account.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/part-of: olm + app.kubernetes.io/name: catalogd + name: controller-manager + namespace: system diff --git a/catalogd/config/components/ca/kustomization.yaml b/catalogd/config/components/ca/kustomization.yaml new file mode 100644 index 000000000..113d2a957 --- /dev/null +++ b/catalogd/config/components/ca/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component +# No namespace is specified here, otherwise, it will overwrite _all_ the other namespaces! +resources: +- resources/issuers.yaml +patches: +- target: + kind: Deployment + name: controller-manager + path: patches/manager_deployment_cacerts.yaml diff --git a/catalogd/config/components/ca/patches/manager_deployment_cacerts.yaml b/catalogd/config/components/ca/patches/manager_deployment_cacerts.yaml new file mode 100644 index 000000000..b5b03633e --- /dev/null +++ b/catalogd/config/components/ca/patches/manager_deployment_cacerts.yaml @@ -0,0 +1,9 @@ +- op: add + path: /spec/template/spec/volumes/- + value: {"name":"olmv1-certificate", "secret":{"secretName":"catalogd-service-cert-git-version", "optional": false, "items": [{"key": "ca.crt", "path": "olm-ca.crt"}]}} +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: {"name":"olmv1-certificate", "readOnly": true, "mountPath":"/var/ca-certs/"} +- op: add + path: /spec/template/spec/containers/0/args/- + value: "--ca-certs-dir=/var/ca-certs" diff --git a/catalogd/config/components/ca/resources/issuers.yaml b/catalogd/config/components/ca/resources/issuers.yaml new file mode 100644 index 000000000..00e149d56 --- /dev/null +++ b/catalogd/config/components/ca/resources/issuers.yaml @@ -0,0 +1,35 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: self-sign-issuer + namespace: cert-manager +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: olmv1-ca + namespace: cert-manager +spec: + isCA: true + commonName: olmv1-ca + secretName: olmv1-ca + secretTemplate: + annotations: + cert-manager.io/allow-direct-injection: "true" + privateKey: + algorithm: ECDSA + size: 256 + issuerRef: + name: self-sign-issuer + kind: Issuer + group: cert-manager.io +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: olmv1-ca +spec: + ca: + secretName: olmv1-ca diff --git a/catalogd/config/components/registries-conf/kustomization.yaml b/catalogd/config/components/registries-conf/kustomization.yaml new file mode 100644 index 000000000..e48262429 --- /dev/null +++ b/catalogd/config/components/registries-conf/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component +namespace: olmv1-system +resources: +- registries_conf_configmap.yaml +patches: +- path: manager_e2e_registries_conf_patch.yaml diff --git a/catalogd/config/components/registries-conf/manager_e2e_registries_conf_patch.yaml b/catalogd/config/components/registries-conf/manager_e2e_registries_conf_patch.yaml new file mode 100644 index 000000000..42012d697 --- /dev/null +++ b/catalogd/config/components/registries-conf/manager_e2e_registries_conf_patch.yaml @@ -0,0 +1,17 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + volumeMounts: + - name: e2e-registries-conf + mountPath: /etc/containers + volumes: + - name: e2e-registries-conf + configMap: + name: e2e-registries-conf diff --git a/catalogd/config/components/registries-conf/registries_conf_configmap.yaml b/catalogd/config/components/registries-conf/registries_conf_configmap.yaml new file mode 100644 index 000000000..3561bbe59 --- /dev/null +++ b/catalogd/config/components/registries-conf/registries_conf_configmap.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: e2e-registries-conf + namespace: system +data: + registries.conf: | + [[registry]] + prefix = "docker-registry.catalogd-e2e.svc:5000" + insecure = true + location = "docker-registry.catalogd-e2e.svc:5000" diff --git a/catalogd/config/components/tls/kustomization.yaml b/catalogd/config/components/tls/kustomization.yaml new file mode 100644 index 000000000..f537d5d14 --- /dev/null +++ b/catalogd/config/components/tls/kustomization.yaml @@ -0,0 +1,21 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component +namespace: olmv1-system +namePrefix: catalogd- +resources: +- resources/certificate.yaml +patches: +- target: + kind: Service + name: service + path: patches/catalogd_service_port.yaml +- target: + kind: Deployment + name: controller-manager + path: patches/manager_deployment_certs.yaml +- target: + group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + name: mutating-webhook-configuration + version: v1 + path: patches/catalogd_webhook.yaml diff --git a/catalogd/config/components/tls/patches/catalogd_service_port.yaml b/catalogd/config/components/tls/patches/catalogd_service_port.yaml new file mode 100644 index 000000000..b5b88bb47 --- /dev/null +++ b/catalogd/config/components/tls/patches/catalogd_service_port.yaml @@ -0,0 +1,6 @@ +- op: replace + path: /spec/ports/0/port + value: 443 +- op: replace + path: /spec/ports/0/name + value: https \ No newline at end of file diff --git a/catalogd/config/components/tls/patches/catalogd_webhook.yaml b/catalogd/config/components/tls/patches/catalogd_webhook.yaml new file mode 100644 index 000000000..cf1a39ec3 --- /dev/null +++ b/catalogd/config/components/tls/patches/catalogd_webhook.yaml @@ -0,0 +1,3 @@ +- op: add + path: /metadata/annotations/cert-manager.io~1inject-ca-from-secret + value: cert-manager/olmv1-ca diff --git a/catalogd/config/components/tls/patches/manager_deployment_certs.yaml b/catalogd/config/components/tls/patches/manager_deployment_certs.yaml new file mode 100644 index 000000000..3d8b33ac3 --- /dev/null +++ b/catalogd/config/components/tls/patches/manager_deployment_certs.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: {"name":"catalogserver-certs", "secret":{"secretName":"catalogd-service-cert-git-version"}} +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: {"name":"catalogserver-certs", "mountPath":"/var/certs"} +- op: add + path: /spec/template/spec/containers/0/args/- + value: "--tls-cert=/var/certs/tls.crt" +- op: add + path: /spec/template/spec/containers/0/args/- + value: "--tls-key=/var/certs/tls.key" diff --git a/catalogd/config/components/tls/resources/certificate.yaml b/catalogd/config/components/tls/resources/certificate.yaml new file mode 100644 index 000000000..be14f8301 --- /dev/null +++ b/catalogd/config/components/tls/resources/certificate.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: service-cert + namespace: system +spec: + secretName: catalogd-service-cert-git-version + dnsNames: + - localhost + - catalogd-service.olmv1-system.svc + - catalogd-service.olmv1-system.svc.cluster.local + privateKey: + algorithm: ECDSA + size: 256 + issuerRef: + kind: ClusterIssuer + group: cert-manager.io + name: olmv1-ca diff --git a/catalogd/config/overlays/cert-manager/kustomization.yaml b/catalogd/config/overlays/cert-manager/kustomization.yaml new file mode 100644 index 000000000..fb27be4f4 --- /dev/null +++ b/catalogd/config/overlays/cert-manager/kustomization.yaml @@ -0,0 +1,9 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../../base/crd +- ../../base/rbac +- ../../base/manager +components: +- ../../components/tls +- ../../components/ca diff --git a/catalogd/config/overlays/e2e/kustomization.yaml b/catalogd/config/overlays/e2e/kustomization.yaml new file mode 100644 index 000000000..dbfd7d737 --- /dev/null +++ b/catalogd/config/overlays/e2e/kustomization.yaml @@ -0,0 +1,12 @@ +# kustomization file for all the e2e's +# DO NOT ADD A NAMESPACE HERE +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ../../base/crd + - ../../base/rbac + - ../../base/manager +components: + - ../../components/tls + - ../../components/registries-conf + - ../../components/ca diff --git a/catalogd/config/rbac/role.yaml b/catalogd/config/rbac/role.yaml new file mode 100644 index 000000000..b0cf5a213 --- /dev/null +++ b/catalogd/config/rbac/role.yaml @@ -0,0 +1,65 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: manager-role +rules: +- apiGroups: + - olm.operatorframework.io + resources: + - clustercatalogs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - olm.operatorframework.io + resources: + - clustercatalogs/finalizers + verbs: + - update +- apiGroups: + - olm.operatorframework.io + resources: + - clustercatalogs/status + verbs: + - get + - patch + - update +- apiGroups: + - "" + resources: + - pods + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - pods/log + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: manager-role + namespace: system +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - get diff --git a/catalogd/config/samples/core_v1_clustercatalog.yaml b/catalogd/config/samples/core_v1_clustercatalog.yaml new file mode 100644 index 000000000..661bf2a6c --- /dev/null +++ b/catalogd/config/samples/core_v1_clustercatalog.yaml @@ -0,0 +1,11 @@ +apiVersion: olm.operatorframework.io/v1 +kind: ClusterCatalog +metadata: + name: operatorhubio +spec: + priority: 0 + source: + type: Image + image: + pollIntervalMinutes: 1440 + ref: quay.io/operatorhubio/catalog:latest diff --git a/catalogd/crd-diff-config.yaml b/catalogd/crd-diff-config.yaml new file mode 100644 index 000000000..8cce39378 --- /dev/null +++ b/catalogd/crd-diff-config.yaml @@ -0,0 +1,109 @@ +checks: + crd: + scope: + enabled: true + existingFieldRemoval: + enabled: true + storedVersionRemoval: + enabled: true + version: + sameVersion: + enabled: true + unhandledFailureMode: "Closed" + enum: + enabled: true + removalEnforcement: "Strict" + additionEnforcement: "Strict" + default: + enabled: true + changeEnforcement: "Strict" + removalEnforcement: "Strict" + additionEnforcement: "Strict" + required: + enabled: true + newEnforcement: "Strict" + type: + enabled: true + changeEnforcement: "Strict" + maximum: + enabled: true + additionEnforcement: "Strict" + decreaseEnforcement: "Strict" + maxItems: + enabled: true + additionEnforcement: "Strict" + decreaseEnforcement: "Strict" + maxProperties: + enabled: true + additionEnforcement: "Strict" + decreaseEnforcement: "Strict" + maxLength: + enabled: true + additionEnforcement: "Strict" + decreaseEnforcement: "Strict" + minimum: + enabled: true + additionEnforcement: "Strict" + increaseEnforcement: "Strict" + minItems: + enabled: true + additionEnforcement: "Strict" + increaseEnforcement: "Strict" + minProperties: + enabled: true + additionEnforcement: "Strict" + increaseEnforcement: "Strict" + minLength: + enabled: true + additionEnforcement: "Strict" + increaseEnforcement: "Strict" + servedVersion: + enabled: true + unhandledFailureMode: "Closed" + enum: + enabled: true + removalEnforcement: "Strict" + additionEnforcement: "Strict" + default: + enabled: true + changeEnforcement: "Strict" + removalEnforcement: "Strict" + additionEnforcement: "Strict" + required: + enabled: true + newEnforcement: "Strict" + type: + enabled: true + changeEnforcement: "Strict" + maximum: + enabled: true + additionEnforcement: "Strict" + decreaseEnforcement: "Strict" + maxItems: + enabled: true + additionEnforcement: "Strict" + decreaseEnforcement: "Strict" + maxProperties: + enabled: true + additionEnforcement: "Strict" + decreaseEnforcement: "Strict" + maxLength: + enabled: true + additionEnforcement: "Strict" + decreaseEnforcement: "Strict" + minimum: + enabled: true + additionEnforcement: "Strict" + increaseEnforcement: "Strict" + minItems: + enabled: true + additionEnforcement: "Strict" + increaseEnforcement: "Strict" + minProperties: + enabled: true + additionEnforcement: "Strict" + increaseEnforcement: "Strict" + minLength: + enabled: true + additionEnforcement: "Strict" + increaseEnforcement: "Strict" diff --git a/catalogd/docs/fetching-catalog-contents.md b/catalogd/docs/fetching-catalog-contents.md new file mode 100644 index 000000000..ccc0ff231 --- /dev/null +++ b/catalogd/docs/fetching-catalog-contents.md @@ -0,0 +1,204 @@ +# `ClusterCatalog` Interface +`catalogd` serves catalog content via a catalog-specific, versioned HTTP(S) endpoint. Clients access catalog information via this API endpoint and a versioned reference of the desired format. Current support includes only a complete catalog download, indicated by the path "api/v1/all", for example if `status.urls.base` is `https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio` then `https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/api/vi/all` would receive the complete FBC for the catalog `operatorhubio`. + + +## Response Format +`catalogd` responses retrieved via the catalog-specific v1 API are encoded as a [JSON Lines](https://jsonlines.org/) stream of File-Based Catalog (FBC) [Meta](https://olm.operatorframework.io/docs/reference/file-based-catalogs/#schema) objects delimited by newlines. + +### Example +For an example JSON-encoded FBC snippet +```json +{ + "schema": "olm.package", + "name": "cockroachdb", + "defaultChannel": "stable-v6.x", +} +{ + "schema": "olm.channel", + "name": "stable-v6.x", + "package": "cockroachdb", + "entries": [ + { + "name": "cockroachdb.v6.0.0", + "skipRange": "<6.0.0" + } + ] +} +{ + "schema": "olm.bundle", + "name": "cockroachdb.v6.0.0", + "package": "cockroachdb", + "image": "quay.io/openshift-community-operators/cockroachdb@sha256:d3016b1507515fc7712f9c47fd9082baf9ccb070aaab58ed0ef6e5abdedde8ba", + "properties": [ + { + "type": "olm.package", + "value": { + "packageName": "cockroachdb", + "version": "6.0.0" + } + }, + ], +} +``` +the corresponding JSON Lines formatted response would be +```json +{"schema":"olm.package","name":"cockroachdb","defaultChannel":"stable-v6.x"} +{"schema":"olm.channel","name":"stable-v6.x","package":"cockroachdb","entries":[{"name":"cockroachdb.v6.0.0","skipRange":"<6.0.0"}]} +{"schema":"olm.bundle","name":"cockroachdb.v6.0.0","package":"cockroachdb","image":"quay.io/openshift-community-operators/cockroachdb@sha256:d3016b1507515fc7712f9c47fd9082baf9ccb070aaab58ed0ef6e5abdedde8ba","properties":[{"type":"olm.package","value":{"packageName":"cockroachdb","version":"6.0.0"}}]} +``` + +## Compression Support + +`catalogd` supports gzip compression of responses, which can significantly reduce associated network traffic. In order to signal to `catalogd` that the client handles compressed responses, the client must include `Accept-Encoding: gzip` as a header in the HTTP request. + +`catalogd` will include a `Content-Encoding: gzip` header in compressed responses. + +Note that `catalogd` will only compress catalogs larger than 1400 bytes. + +### Example + +The demo below +1. retrieves plaintext catalog content (and saves to file 1) +2. adds the `Accept-Encoding` header and retrieves compressed content +3. adds the `Accept-Encofing` header and uses curl to decompress the response (and saves to file 2) +4. uses diff to demonstrate that there is no difference between the contents of files 1 and 2 + + +[![asciicast](https://asciinema.org/a/668823.svg)](https://asciinema.org/a/668823) + + + +# Fetching `ClusterCatalog` contents from the Catalogd HTTP Server +This section covers how to fetch the contents for a `ClusterCatalog` from the +Catalogd HTTP(S) Server. + +For example purposes we make the following assumption: +- A `ClusterCatalog` named `operatorhubio` has been created and successfully unpacked +(denoted in the `ClusterCatalog.Status`) + +**NOTE:** By default, Catalogd is configured to use TLS with self-signed certificates. +For local development, consider skipping TLS verification, such as `curl -k`, or reference external material +on self-signed certificate verification. + +`ClusterCatalog` CRs have a `status.urls.base` field which identifies the catalog-specific API to access the catalog content: + +```yaml + status: + . + . + urls: + base: https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio + resolvedSource: + image: + ref: quay.io/operatorhubio/catalog@sha256:e53267559addc85227c2a7901ca54b980bc900276fc24d3f4db0549cb38ecf76 + type: Image +``` + +## On cluster + +When making a request for the complete contents of the `operatorhubio` `ClusterCatalog` from within +the cluster, clients would combine `status.urls.base` with the desired API service and issue an HTTP GET request for the URL. + +For example, to receive the complete catalog data for the `operatorhubio` catalog indicated above, the client would append the service point designator `api/v1/all`, like: + +`https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/api/v1/all`. + +An example command to run a `Pod` to `curl` the catalog contents: +```sh +kubectl run fetcher --image=curlimages/curl:latest -- curl https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/api/v1/all +``` + +## Off cluster + +When making a request for the contents of the `operatorhubio` `ClusterCatalog` from outside +the cluster, we have to perform an extra step: +1. Port forward the `catalogd-service` service in the `olmv1-system` namespace: +```sh +kubectl -n olmv1-system port-forward svc/catalogd-service 8080:443 +``` + +Once the service has been successfully forwarded to a localhost port, issue a HTTP `GET` +request to `https://localhost:8080/catalogs/operatorhubio/api/v1/all` + +An example `curl` request that assumes the port-forwarding is mapped to port 8080 on the local machine: +```sh +curl http://localhost:8080/catalogs/operatorhubio/api/v1/all +``` + +# Fetching `ClusterCatalog` contents from the `Catalogd` Service outside of the cluster + +This section outlines a way of exposing the `Catalogd` Service's endpoints outside the cluster and then accessing the catalog contents using `Ingress`. We will be using `Ingress NGINX` Controller for the sake of this example but you are welcome to use the `Ingress` Controller of your choice. + +**Prerequisites** + +- [Install kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) +- Assuming `kind` is installed, create a `kind` cluster with `extraPortMappings` and `node-labels` as shown in the [kind documentation](https://kind.sigs.k8s.io/docs/user/ingress/) +- Install latest version of `Catalogd` by navigating to the [releases page](https://github.com/operator-framework/catalogd/releases) and following the install instructions included in the release you want to install. +- Install the `Ingress NGINX` Controller by running the below command: + + ```sh + $ kubectl apply -k https://github.com/operator-framework/catalogd/tree/main/config/nginx-ingress + ``` + By running that above command, the `Ingress` Controller is installed. Along with it, the `Ingress` Resource will be applied automatically as well, thereby creating an `Ingress` Object on the cluster. + +1. Once the prerequisites are satisfied, create a `ClusterCatalog` object that points to the OperatorHub Community catalog by running the following command: + + ```sh + $ kubectl apply -f - << EOF + apiVersion: olm.operatorframework.io/v1 + kind: ClusterCatalog + metadata: + name: operatorhubio + spec: + source: + type: Image + image: + ref: quay.io/operatorhubio/catalog:latest + EOF + ``` + +1. Before proceeding further, let's verify that the `ClusterCatalog` object was created successfully by running the below command: + + ```sh + $ kubectl describe catalog/operatorhubio + ``` + +1. At this point the `ClusterCatalog` object exists and `Ingress` controller is ready to process requests. The sample `Ingress` Resource that was created during Step 4 of Prerequisites is shown as below: + + ```yaml + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + name: catalogd-nginx-ingress + namespace: olmv1-system + spec: + ingressClassName: nginx + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: catalogd-service + port: + number: 80 + ``` + Let's verify that the `Ingress` object got created successfully from the sample by running the following command: + + ```sh + $ kubectl describe ingress/catalogd-ingress -n olmv1-system + ``` + +1. Run the below example `curl` request to retrieve all of the catalog contents: + + ```sh + $ curl https://
/catalogs/operatorhubio/api/v1/all + ``` + + To obtain `address` of the ingress object, you can run the below command and look for the value in the `ADDRESS` field from output: + ```sh + $ kubectl -n olmv1-system get ingress + ``` + + You can further use the `curl` commands outlined in the [Catalogd README](https://github.com/operator-framework/catalogd/blob/main/README.md) to filter out the JSON content by list of bundles, channels & packages. diff --git a/catalogd/hack/scripts/demo-script.sh b/catalogd/hack/scripts/demo-script.sh new file mode 100755 index 000000000..b0f1feaa7 --- /dev/null +++ b/catalogd/hack/scripts/demo-script.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# +# Welcome to the catalogd demo +# +trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT + + +kind delete cluster +kind create cluster +kubectl cluster-info --context kind-kind +sleep 10 + +# use the install script from the latest github release +curl -L -s https://github.com/operator-framework/catalogd/releases/latest/download/install.sh | bash + +# inspect crds (clustercatalog) +kubectl get crds -A +kubectl get clustercatalog -A + +echo "... checking catalogd controller is available" +kubectl wait --for=condition=Available -n olmv1-system deploy/catalogd-controller-manager --timeout=1m +echo "... checking clustercatalog is serving" +kubectl wait --for=condition=Serving clustercatalog/operatorhubio --timeout=60s +echo "... checking clustercatalog is finished unpacking" +kubectl wait --for=condition=Progressing=False clustercatalog/operatorhubio --timeout=60s + +# port forward the catalogd-service service to interact with the HTTP server serving catalog contents +(kubectl -n olmv1-system port-forward svc/catalogd-service 8081:443)& + +sleep 3 + +# check what 'packages' are available in this catalog +curl -k https://localhost:8081/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.package") | .name' +# check what channels are included in the wavefront package +curl -k https://localhost:8081/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.channel") | select(.package == "wavefront") | .name' +# check what bundles are included in the wavefront package +curl -k https://localhost:8081/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.bundle") | select(.package == "wavefront") | .name' + diff --git a/catalogd/hack/scripts/generate-asciidemo.sh b/catalogd/hack/scripts/generate-asciidemo.sh new file mode 100755 index 000000000..aa7262182 --- /dev/null +++ b/catalogd/hack/scripts/generate-asciidemo.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +trap cleanup SIGINT SIGTERM EXIT + +SCRIPTPATH="$( cd -- "$(dirname "$0")" > /dev/null 2>&1 ; pwd -P )" + +function check_prereq() { + prog=$1 + if ! command -v ${prog} &> /dev/null + then + echo "unable to find prerequisite: $1" + exit 1 + fi +} + +function cleanup() { + if [ -d $WKDIR ] + then + rm -rf $WKDIR + fi +} + +function usage() { + echo "$0 [options]" + echo "where options is" + echo " h help (this message)" + exit 1 +} + +set +u +while getopts 'h' flag; do + case "${flag}" in + h) usage ;; + esac + shift +done +set -u + +WKDIR=$(mktemp -td generate-asciidemo.XXXXX) +if [ ! -d ${WKDIR} ] +then + echo "unable to create temporary workspace" + exit 2 +fi + +for prereq in "asciinema curl" +do + check_prereq ${prereq} +done + + +curl https://raw.githubusercontent.com/zechris/asciinema-rec_script/main/bin/asciinema-rec_script -o ${WKDIR}/asciinema-rec_script +chmod +x ${WKDIR}/asciinema-rec_script +screencast=${WKDIR}/catalogd-demo.cast ${WKDIR}/asciinema-rec_script ${SCRIPTPATH}/demo-script.sh + +asciinema upload ${WKDIR}/catalogd-demo.cast + diff --git a/catalogd/hack/scripts/generate-gzip-asciidemo.sh b/catalogd/hack/scripts/generate-gzip-asciidemo.sh new file mode 100755 index 000000000..c02c54d7b --- /dev/null +++ b/catalogd/hack/scripts/generate-gzip-asciidemo.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +trap cleanup SIGINT SIGTERM EXIT + +SCRIPTPATH="$( cd -- "$(dirname "$0")" > /dev/null 2>&1 ; pwd -P )" + +function check_prereq() { + prog=$1 + if ! command -v ${prog} &> /dev/null + then + echo "unable to find prerequisite: $1" + exit 1 + fi +} + +function cleanup() { + if [ -d $WKDIR ] + then + rm -rf $WKDIR + fi +} + +function usage() { + echo "$0 [options]" + echo "where options is" + echo " h help (this message)" + exit 1 +} + +set +u +while getopts 'h' flag; do + case "${flag}" in + h) usage ;; + esac + shift +done +set -u + +WKDIR=$(mktemp -td generate-asciidemo.XXXXX) +if [ ! -d ${WKDIR} ] +then + echo "unable to create temporary workspace" + exit 2 +fi + +for prereq in "asciinema curl" +do + check_prereq ${prereq} +done + + +curl https://raw.githubusercontent.com/zechris/asciinema-rec_script/main/bin/asciinema-rec_script -o ${WKDIR}/asciinema-rec_script +chmod +x ${WKDIR}/asciinema-rec_script +screencast=${WKDIR}/catalogd-demo.cast ${WKDIR}/asciinema-rec_script ${SCRIPTPATH}/gzip-demo-script.sh + +asciinema upload ${WKDIR}/catalogd-demo.cast + diff --git a/catalogd/hack/scripts/gzip-demo-script.sh b/catalogd/hack/scripts/gzip-demo-script.sh new file mode 100755 index 000000000..2cd1bb794 --- /dev/null +++ b/catalogd/hack/scripts/gzip-demo-script.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT +# Welcome to the catalogd demo +make run + +# create a clustercatalog +kubectl apply -f $HOME/devel/tmp/operatorhubio-clustercatalog.yaml +# shows catalog +kubectl get clustercatalog -A +# waiting for clustercatalog to report ready status +time kubectl wait --for=condition=Unpacked clustercatalog/operatorhubio --timeout=1m + +# port forward the catalogd-service service to interact with the HTTP server serving catalog contents +(kubectl -n olmv1-system port-forward svc/catalogd-service 8080:443)& +sleep 5 + +# retrieve catalog as plaintext JSONlines +curl -k -vvv https://localhost:8080/catalogs/operatorhubio/api/v1/all --output /tmp/cat-content.json + +# advertise handling of compressed content +curl -vvv -k https://localhost:8080/catalogs/operatorhubio/api/v1/all -H 'Accept-Encoding: gzip' --output /tmp/cat-content.gz + +# let curl handle the compress/decompress for us +curl -vvv --compressed -k https://localhost:8080/catalogs/operatorhubio/api/v1/all --output /tmp/cat-content-decompressed.txt + +# show that there's no content change with changed format +diff /tmp/cat-content.json /tmp/cat-content-decompressed.txt + diff --git a/catalogd/internal/controllers/core/clustercatalog_controller.go b/catalogd/internal/controllers/core/clustercatalog_controller.go new file mode 100644 index 000000000..4eedd52df --- /dev/null +++ b/catalogd/internal/controllers/core/clustercatalog_controller.go @@ -0,0 +1,443 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package core + +import ( + "context" // #nosec + "errors" + "fmt" + "slices" + "sync" + "time" + + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/utils/ptr" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + crfinalizer "sigs.k8s.io/controller-runtime/pkg/finalizer" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" + "github.com/operator-framework/operator-controller/catalogd/internal/source" + "github.com/operator-framework/operator-controller/catalogd/internal/storage" +) + +const ( + fbcDeletionFinalizer = "olm.operatorframework.io/delete-server-cache" + // CatalogSources are polled if PollInterval is mentioned, in intervals of wait.Jitter(pollDuration, maxFactor) + // wait.Jitter returns a time.Duration between pollDuration and pollDuration + maxFactor * pollDuration. + requeueJitterMaxFactor = 0.01 +) + +// ClusterCatalogReconciler reconciles a Catalog object +type ClusterCatalogReconciler struct { + client.Client + Unpacker source.Unpacker + Storage storage.Instance + + finalizers crfinalizer.Finalizers + + // TODO: The below storedCatalogs fields are used for a quick a hack that helps + // us correctly populate a ClusterCatalog's status. The fact that we need + // these is indicative of a larger problem with the design of one or both + // of the Unpacker and Storage interfaces. We should fix this. + storedCatalogsMu sync.RWMutex + storedCatalogs map[string]storedCatalogData +} + +type storedCatalogData struct { + observedGeneration int64 + unpackResult source.Result +} + +//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clustercatalogs,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clustercatalogs/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clustercatalogs/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.11.0/pkg/reconcile +func (r *ClusterCatalogReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + l := log.FromContext(ctx).WithName("catalogd-controller") + ctx = log.IntoContext(ctx, l) + + l.Info("reconcile starting") + defer l.Info("reconcile ending") + + existingCatsrc := catalogdv1.ClusterCatalog{} + if err := r.Client.Get(ctx, req.NamespacedName, &existingCatsrc); err != nil { + return ctrl.Result{}, client.IgnoreNotFound(err) + } + + reconciledCatsrc := existingCatsrc.DeepCopy() + res, reconcileErr := r.reconcile(ctx, reconciledCatsrc) + + // If we encounter an error, we should delete the stored catalog metadata + // which represents the state of a successfully unpacked catalog. Deleting + // this state ensures that we will continue retrying the unpacking process + // until it succeeds. + if reconcileErr != nil { + r.deleteStoredCatalog(reconciledCatsrc.Name) + } + + // Do checks before any Update()s, as Update() may modify the resource structure! + updateStatus := !equality.Semantic.DeepEqual(existingCatsrc.Status, reconciledCatsrc.Status) + updateFinalizers := !equality.Semantic.DeepEqual(existingCatsrc.Finalizers, reconciledCatsrc.Finalizers) + unexpectedFieldsChanged := checkForUnexpectedFieldChange(existingCatsrc, *reconciledCatsrc) + + if unexpectedFieldsChanged { + panic("spec or metadata changed by reconciler") + } + + // Save the finalizers off to the side. If we update the status, the reconciledCatsrc will be updated + // to contain the new state of the ClusterCatalog, which contains the status update, but (critically) + // does not contain the finalizers. After the status update, we need to re-add the finalizers to the + // reconciledCatsrc before updating the object. + finalizers := reconciledCatsrc.Finalizers + + if updateStatus { + if err := r.Client.Status().Update(ctx, reconciledCatsrc); err != nil { + reconcileErr = errors.Join(reconcileErr, fmt.Errorf("error updating status: %v", err)) + } + } + + reconciledCatsrc.Finalizers = finalizers + + if updateFinalizers { + if err := r.Client.Update(ctx, reconciledCatsrc); err != nil { + reconcileErr = errors.Join(reconcileErr, fmt.Errorf("error updating finalizers: %v", err)) + } + } + + return res, reconcileErr +} + +// SetupWithManager sets up the controller with the Manager. +func (r *ClusterCatalogReconciler) SetupWithManager(mgr ctrl.Manager) error { + r.storedCatalogsMu.Lock() + defer r.storedCatalogsMu.Unlock() + r.storedCatalogs = make(map[string]storedCatalogData) + + if err := r.setupFinalizers(); err != nil { + return fmt.Errorf("failed to setup finalizers: %v", err) + } + + return ctrl.NewControllerManagedBy(mgr). + For(&catalogdv1.ClusterCatalog{}). + Complete(r) +} + +// Note: This function always returns ctrl.Result{}. The linter +// fusses about this as we could instead just return error. This was +// discussed in https://github.com/operator-framework/rukpak/pull/635#discussion_r1229859464 +// and the consensus was that it is better to keep the ctrl.Result return +// type so that if we do end up needing to return something else we don't forget +// to add the ctrl.Result type back as a return value. Adding a comment to ignore +// linting from the linter that was fussing about this. +// nolint:unparam +func (r *ClusterCatalogReconciler) reconcile(ctx context.Context, catalog *catalogdv1.ClusterCatalog) (ctrl.Result, error) { + l := log.FromContext(ctx) + // Check if the catalog availability is set to disabled, if true then + // unset base URL, delete it from the cache and set appropriate status + if catalog.Spec.AvailabilityMode == catalogdv1.AvailabilityModeUnavailable { + // Delete the catalog from local cache + err := r.deleteCatalogCache(ctx, catalog) + if err != nil { + return ctrl.Result{}, err + } + + // Set status.conditions[type=Progressing] to False as we are done with + // all that needs to be done with the catalog + updateStatusProgressingUserSpecifiedUnavailable(&catalog.Status, catalog.GetGeneration()) + + // Remove the fbcDeletionFinalizer as we do not want a finalizer attached to the catalog + // when it is disabled. Because the finalizer serves no purpose now. + controllerutil.RemoveFinalizer(catalog, fbcDeletionFinalizer) + + return ctrl.Result{}, nil + } + + finalizeResult, err := r.finalizers.Finalize(ctx, catalog) + if err != nil { + return ctrl.Result{}, err + } + if finalizeResult.Updated || finalizeResult.StatusUpdated { + // On create: make sure the finalizer is applied before we do anything + // On delete: make sure we do nothing after the finalizer is removed + return ctrl.Result{}, nil + } + + // TODO: The below algorithm to get the current state based on an in-memory + // storedCatalogs map is a hack that helps us keep the ClusterCatalog's + // status up-to-date. The fact that we need this setup is indicative of + // a larger problem with the design of one or both of the Unpacker and + // Storage interfaces and/or their interactions. We should fix this. + expectedStatus, storedCatalog, hasStoredCatalog := r.getCurrentState(catalog) + + // If any of the following are true, we need to unpack the catalog: + // - we don't have a stored catalog in the map + // - we have a stored catalog, but the content doesn't exist on disk + // - we have a stored catalog, the content exists, but the expected status differs from the actual status + // - we have a stored catalog, the content exists, the status looks correct, but the catalog generation is different from the observed generation in the stored catalog + // - we have a stored catalog, the content exists, the status looks correct and reflects the catalog generation, but it is time to poll again + needsUnpack := false + switch { + case !hasStoredCatalog: + l.Info("unpack required: no cached catalog metadata found for this catalog") + needsUnpack = true + case !r.Storage.ContentExists(catalog.Name): + l.Info("unpack required: no stored content found for this catalog") + needsUnpack = true + case !equality.Semantic.DeepEqual(catalog.Status, *expectedStatus): + l.Info("unpack required: current ClusterCatalog status differs from expected status") + needsUnpack = true + case catalog.Generation != storedCatalog.observedGeneration: + l.Info("unpack required: catalog generation differs from observed generation") + needsUnpack = true + case r.needsPoll(storedCatalog.unpackResult.LastSuccessfulPollAttempt.Time, catalog): + l.Info("unpack required: poll duration has elapsed") + needsUnpack = true + } + + if !needsUnpack { + // No need to update the status because we've already checked + // that it is set correctly. Otherwise, we'd be unpacking again. + return nextPollResult(storedCatalog.unpackResult.LastSuccessfulPollAttempt.Time, catalog), nil + } + + unpackResult, err := r.Unpacker.Unpack(ctx, catalog) + if err != nil { + unpackErr := fmt.Errorf("source catalog content: %w", err) + updateStatusProgressing(&catalog.Status, catalog.GetGeneration(), unpackErr) + return ctrl.Result{}, unpackErr + } + + switch unpackResult.State { + case source.StateUnpacked: + // TODO: We should check to see if the unpacked result has the same content + // as the already unpacked content. If it does, we should skip this rest + // of the unpacking steps. + err := r.Storage.Store(ctx, catalog.Name, unpackResult.FS) + if err != nil { + storageErr := fmt.Errorf("error storing fbc: %v", err) + updateStatusProgressing(&catalog.Status, catalog.GetGeneration(), storageErr) + return ctrl.Result{}, storageErr + } + baseURL := r.Storage.BaseURL(catalog.Name) + + updateStatusProgressing(&catalog.Status, catalog.GetGeneration(), nil) + updateStatusServing(&catalog.Status, *unpackResult, baseURL, catalog.GetGeneration()) + default: + panic(fmt.Sprintf("unknown unpack state %q", unpackResult.State)) + } + + r.storedCatalogsMu.Lock() + r.storedCatalogs[catalog.Name] = storedCatalogData{ + unpackResult: *unpackResult, + observedGeneration: catalog.GetGeneration(), + } + r.storedCatalogsMu.Unlock() + return nextPollResult(unpackResult.LastSuccessfulPollAttempt.Time, catalog), nil +} + +func (r *ClusterCatalogReconciler) getCurrentState(catalog *catalogdv1.ClusterCatalog) (*catalogdv1.ClusterCatalogStatus, storedCatalogData, bool) { + r.storedCatalogsMu.RLock() + storedCatalog, hasStoredCatalog := r.storedCatalogs[catalog.Name] + r.storedCatalogsMu.RUnlock() + + expectedStatus := catalog.Status.DeepCopy() + + // Set expected status based on what we see in the stored catalog + clearUnknownConditions(expectedStatus) + if hasStoredCatalog && r.Storage.ContentExists(catalog.Name) { + updateStatusServing(expectedStatus, storedCatalog.unpackResult, r.Storage.BaseURL(catalog.Name), storedCatalog.observedGeneration) + updateStatusProgressing(expectedStatus, storedCatalog.observedGeneration, nil) + } + + return expectedStatus, storedCatalog, hasStoredCatalog +} + +func nextPollResult(lastSuccessfulPoll time.Time, catalog *catalogdv1.ClusterCatalog) ctrl.Result { + var requeueAfter time.Duration + switch catalog.Spec.Source.Type { + case catalogdv1.SourceTypeImage: + if catalog.Spec.Source.Image != nil && catalog.Spec.Source.Image.PollIntervalMinutes != nil { + pollDuration := time.Duration(*catalog.Spec.Source.Image.PollIntervalMinutes) * time.Minute + jitteredDuration := wait.Jitter(pollDuration, requeueJitterMaxFactor) + requeueAfter = time.Until(lastSuccessfulPoll.Add(jitteredDuration)) + } + } + return ctrl.Result{RequeueAfter: requeueAfter} +} + +func clearUnknownConditions(status *catalogdv1.ClusterCatalogStatus) { + knownTypes := sets.New[string]( + catalogdv1.TypeServing, + catalogdv1.TypeProgressing, + ) + status.Conditions = slices.DeleteFunc(status.Conditions, func(cond metav1.Condition) bool { + return !knownTypes.Has(cond.Type) + }) +} + +func updateStatusProgressing(status *catalogdv1.ClusterCatalogStatus, generation int64, err error) { + progressingCond := metav1.Condition{ + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonSucceeded, + Message: "Successfully unpacked and stored content from resolved source", + ObservedGeneration: generation, + } + + if err != nil { + progressingCond.Status = metav1.ConditionTrue + progressingCond.Reason = catalogdv1.ReasonRetrying + progressingCond.Message = err.Error() + } + + if errors.Is(err, reconcile.TerminalError(nil)) { + progressingCond.Status = metav1.ConditionFalse + progressingCond.Reason = catalogdv1.ReasonBlocked + } + + meta.SetStatusCondition(&status.Conditions, progressingCond) +} + +func updateStatusServing(status *catalogdv1.ClusterCatalogStatus, result source.Result, baseURL string, generation int64) { + status.ResolvedSource = result.ResolvedSource + if status.URLs == nil { + status.URLs = &catalogdv1.ClusterCatalogURLs{} + } + status.URLs.Base = baseURL + status.LastUnpacked = ptr.To(metav1.NewTime(result.UnpackTime)) + meta.SetStatusCondition(&status.Conditions, metav1.Condition{ + Type: catalogdv1.TypeServing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonAvailable, + Message: "Serving desired content from resolved source", + ObservedGeneration: generation, + }) +} + +func updateStatusProgressingUserSpecifiedUnavailable(status *catalogdv1.ClusterCatalogStatus, generation int64) { + // Set Progressing condition to True with reason Succeeded + // since we have successfully progressed to the unavailable + // availability mode and are ready to progress to any future + // desired state. + progressingCond := metav1.Condition{ + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonSucceeded, + Message: "Catalog availability mode is set to Unavailable", + ObservedGeneration: generation, + } + + // Set Serving condition to False with reason UserSpecifiedUnavailable + // so that users of this condition are aware that this catalog is + // intentionally not being served + servingCond := metav1.Condition{ + Type: catalogdv1.TypeServing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonUserSpecifiedUnavailable, + Message: "Catalog availability mode is set to Unavailable", + ObservedGeneration: generation, + } + + meta.SetStatusCondition(&status.Conditions, progressingCond) + meta.SetStatusCondition(&status.Conditions, servingCond) +} + +func updateStatusNotServing(status *catalogdv1.ClusterCatalogStatus, generation int64) { + status.ResolvedSource = nil + status.URLs = nil + status.LastUnpacked = nil + meta.SetStatusCondition(&status.Conditions, metav1.Condition{ + Type: catalogdv1.TypeServing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonUnavailable, + ObservedGeneration: generation, + }) +} + +func (r *ClusterCatalogReconciler) needsPoll(lastSuccessfulPoll time.Time, catalog *catalogdv1.ClusterCatalog) bool { + // If polling is disabled, we don't need to poll. + if catalog.Spec.Source.Image.PollIntervalMinutes == nil { + return false + } + + // Only poll if the next poll time is in the past. + nextPoll := lastSuccessfulPoll.Add(time.Duration(*catalog.Spec.Source.Image.PollIntervalMinutes) * time.Minute) + return nextPoll.Before(time.Now()) +} + +// Compare resources - ignoring status & metadata.finalizers +func checkForUnexpectedFieldChange(a, b catalogdv1.ClusterCatalog) bool { + a.Status, b.Status = catalogdv1.ClusterCatalogStatus{}, catalogdv1.ClusterCatalogStatus{} + a.Finalizers, b.Finalizers = []string{}, []string{} + return !equality.Semantic.DeepEqual(a, b) +} + +type finalizerFunc func(ctx context.Context, obj client.Object) (crfinalizer.Result, error) + +func (f finalizerFunc) Finalize(ctx context.Context, obj client.Object) (crfinalizer.Result, error) { + return f(ctx, obj) +} + +func (r *ClusterCatalogReconciler) setupFinalizers() error { + f := crfinalizer.NewFinalizers() + err := f.Register(fbcDeletionFinalizer, finalizerFunc(func(ctx context.Context, obj client.Object) (crfinalizer.Result, error) { + catalog, ok := obj.(*catalogdv1.ClusterCatalog) + if !ok { + panic("could not convert object to clusterCatalog") + } + err := r.deleteCatalogCache(ctx, catalog) + return crfinalizer.Result{StatusUpdated: true}, err + })) + if err != nil { + return err + } + r.finalizers = f + return nil +} + +func (r *ClusterCatalogReconciler) deleteStoredCatalog(catalogName string) { + r.storedCatalogsMu.Lock() + defer r.storedCatalogsMu.Unlock() + delete(r.storedCatalogs, catalogName) +} + +func (r *ClusterCatalogReconciler) deleteCatalogCache(ctx context.Context, catalog *catalogdv1.ClusterCatalog) error { + if err := r.Storage.Delete(catalog.Name); err != nil { + updateStatusProgressing(&catalog.Status, catalog.GetGeneration(), err) + return err + } + updateStatusNotServing(&catalog.Status, catalog.GetGeneration()) + if err := r.Unpacker.Cleanup(ctx, catalog); err != nil { + updateStatusProgressing(&catalog.Status, catalog.GetGeneration(), err) + return err + } + r.deleteStoredCatalog(catalog.Name) + return nil +} diff --git a/catalogd/internal/controllers/core/clustercatalog_controller_test.go b/catalogd/internal/controllers/core/clustercatalog_controller_test.go new file mode 100644 index 000000000..7b6463e36 --- /dev/null +++ b/catalogd/internal/controllers/core/clustercatalog_controller_test.go @@ -0,0 +1,1060 @@ +package core + +import ( + "context" + "errors" + "fmt" + "io/fs" + "net/http" + "testing" + "testing/fstest" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" + "github.com/operator-framework/operator-controller/catalogd/internal/source" + "github.com/operator-framework/operator-controller/catalogd/internal/storage" +) + +var _ source.Unpacker = &MockSource{} + +// MockSource is a utility for mocking out an Unpacker source +type MockSource struct { + // result is the result that should be returned when MockSource.Unpack is called + result *source.Result + + // error is the error to be returned when MockSource.Unpack is called + unpackError error + + // cleanupError is the error to be returned when MockSource.Cleanup is called + cleanupError error +} + +func (ms *MockSource) Unpack(_ context.Context, _ *catalogdv1.ClusterCatalog) (*source.Result, error) { + if ms.unpackError != nil { + return nil, ms.unpackError + } + + return ms.result, nil +} + +func (ms *MockSource) Cleanup(_ context.Context, _ *catalogdv1.ClusterCatalog) error { + return ms.cleanupError +} + +var _ storage.Instance = &MockStore{} + +type MockStore struct { + shouldError bool +} + +func (m MockStore) Store(_ context.Context, _ string, _ fs.FS) error { + if m.shouldError { + return errors.New("mockstore store error") + } + return nil +} + +func (m MockStore) Delete(_ string) error { + if m.shouldError { + return errors.New("mockstore delete error") + } + return nil +} + +func (m MockStore) BaseURL(_ string) string { + return "URL" +} + +func (m MockStore) StorageServerHandler() http.Handler { + panic("not needed") +} + +func (m MockStore) ContentExists(_ string) bool { + return true +} + +func TestCatalogdControllerReconcile(t *testing.T) { + for _, tt := range []struct { + name string + catalog *catalogdv1.ClusterCatalog + expectedError error + shouldPanic bool + expectedCatalog *catalogdv1.ClusterCatalog + source source.Unpacker + store storage.Instance + }{ + { + name: "invalid source type, panics", + source: &MockSource{}, + store: &MockStore{}, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: "invalid", + }, + }, + }, + shouldPanic: true, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: "invalid", + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonBlocked, + }, + }, + }, + }, + }, + { + name: "valid source type, unpack returns error, status updated to reflect error state and error is returned", + expectedError: fmt.Errorf("source catalog content: %w", fmt.Errorf("mocksource error")), + source: &MockSource{ + unpackError: errors.New("mocksource error"), + }, + store: &MockStore{}, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + }, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonRetrying, + }, + }, + }, + }, + }, + { + name: "valid source type, unpack returns terminal error, status updated to reflect terminal error state(Blocked) and error is returned", + expectedError: fmt.Errorf("source catalog content: %w", reconcile.TerminalError(fmt.Errorf("mocksource terminal error"))), + source: &MockSource{ + unpackError: reconcile.TerminalError(errors.New("mocksource terminal error")), + }, + store: &MockStore{}, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + }, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonBlocked, + }, + }, + }, + }, + }, + { + name: "valid source type, unpack state == Unpacked, should reflect in status that it's progressing, and is serving", + source: &MockSource{ + result: &source.Result{ + State: source.StateUnpacked, + FS: &fstest.MapFS{}, + ResolvedSource: &catalogdv1.ResolvedCatalogSource{ + Image: &catalogdv1.ResolvedImageSource{ + Ref: "my.org/someimage@someSHA256Digest", + }, + }, + }, + }, + store: &MockStore{}, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + }, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + URLs: &catalogdv1.ClusterCatalogURLs{Base: "URL"}, + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonAvailable, + }, + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonSucceeded, + }, + }, + ResolvedSource: &catalogdv1.ResolvedCatalogSource{ + Image: &catalogdv1.ResolvedImageSource{ + Ref: "my.org/someimage@someSHA256Digest", + }, + }, + LastUnpacked: &metav1.Time{}, + }, + }, + }, + { + name: "valid source type, unpack state == Unpacked, storage fails, failure reflected in status and error returned", + expectedError: fmt.Errorf("error storing fbc: mockstore store error"), + source: &MockSource{ + result: &source.Result{ + State: source.StateUnpacked, + FS: &fstest.MapFS{}, + }, + }, + store: &MockStore{ + shouldError: true, + }, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + }, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonRetrying, + }, + }, + }, + }, + }, + { + name: "storage finalizer not set, storage finalizer gets set", + source: &MockSource{ + result: &source.Result{ + State: source.StateUnpacked, + FS: &fstest.MapFS{}, + }, + }, + store: &MockStore{}, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + }, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + }, + }, + { + name: "storage finalizer set, catalog deletion timestamp is not zero (or nil), finalizer removed", + source: &MockSource{ + result: &source.Result{ + State: source.StateUnpacked, + FS: &fstest.MapFS{}, + }, + }, + store: &MockStore{}, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + DeletionTimestamp: &metav1.Time{Time: time.Date(2023, time.October, 10, 4, 19, 0, 0, time.UTC)}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + LastUnpacked: &metav1.Time{}, + ResolvedSource: &catalogdv1.ResolvedCatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ResolvedImageSource{ + Ref: "", + }, + }, + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonAvailable, + }, + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonSucceeded, + }, + }, + }, + }, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{}, + DeletionTimestamp: &metav1.Time{Time: time.Date(2023, time.October, 10, 4, 19, 0, 0, time.UTC)}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonUnavailable, + }, + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonSucceeded, + }, + }, + }, + }, + }, + { + name: "storage finalizer set, catalog deletion timestamp is not zero (or nil), storage delete failed, error returned, finalizer not removed and catalog continues serving", + expectedError: fmt.Errorf("finalizer %q failed: %w", fbcDeletionFinalizer, fmt.Errorf("mockstore delete error")), + source: &MockSource{ + result: &source.Result{ + State: source.StateUnpacked, + FS: &fstest.MapFS{}, + }, + }, + store: &MockStore{ + shouldError: true, + }, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + DeletionTimestamp: &metav1.Time{Time: time.Date(2023, time.October, 10, 4, 19, 0, 0, time.UTC)}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + URLs: &catalogdv1.ClusterCatalogURLs{Base: "URL"}, + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonSucceeded, + }, + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonAvailable, + }, + }, + }, + }, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + DeletionTimestamp: &metav1.Time{Time: time.Date(2023, time.October, 10, 4, 19, 0, 0, time.UTC)}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + URLs: &catalogdv1.ClusterCatalogURLs{Base: "URL"}, + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonRetrying, + }, + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonAvailable, + }, + }, + }, + }, + }, + { + name: "storage finalizer set, catalog deletion timestamp is not zero (or nil), unpack cleanup failed, error returned, finalizer not removed but catalog stops serving", + expectedError: fmt.Errorf("finalizer %q failed: %w", fbcDeletionFinalizer, fmt.Errorf("mocksource cleanup error")), + source: &MockSource{ + unpackError: nil, + cleanupError: fmt.Errorf("mocksource cleanup error"), + }, + store: &MockStore{ + shouldError: false, + }, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + DeletionTimestamp: &metav1.Time{Time: time.Date(2023, time.October, 10, 4, 19, 0, 0, time.UTC)}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonSucceeded, + }, + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonAvailable, + }, + }, + }, + }, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + DeletionTimestamp: &metav1.Time{Time: time.Date(2023, time.October, 10, 4, 19, 0, 0, time.UTC)}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: catalogdv1.ClusterCatalogStatus{ + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonRetrying, + }, + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonUnavailable, + }, + }, + }, + }, + }, + { + name: "catalog availability set to disabled, status.urls should get unset", + source: &MockSource{ + result: &source.Result{ + State: source.StateUnpacked, + FS: &fstest.MapFS{}, + }, + }, + store: &MockStore{}, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + AvailabilityMode: catalogdv1.AvailabilityModeUnavailable, + }, + Status: catalogdv1.ClusterCatalogStatus{ + URLs: &catalogdv1.ClusterCatalogURLs{Base: "URL"}, + LastUnpacked: &metav1.Time{}, + ResolvedSource: &catalogdv1.ResolvedCatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ResolvedImageSource{ + Ref: "", + }, + }, + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonAvailable, + }, + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonSucceeded, + }, + }, + }, + }, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + AvailabilityMode: catalogdv1.AvailabilityModeUnavailable, + }, + Status: catalogdv1.ClusterCatalogStatus{ + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonUserSpecifiedUnavailable, + }, + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonSucceeded, + }, + }, + }, + }, + }, + { + name: "catalog availability set to disabled, finalizer should get removed", + source: &MockSource{ + result: &source.Result{ + State: source.StateUnpacked, + FS: &fstest.MapFS{}, + }, + }, + store: &MockStore{}, + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + AvailabilityMode: catalogdv1.AvailabilityModeUnavailable, + }, + Status: catalogdv1.ClusterCatalogStatus{ + URLs: &catalogdv1.ClusterCatalogURLs{Base: "URL"}, + LastUnpacked: &metav1.Time{}, + ResolvedSource: &catalogdv1.ResolvedCatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ResolvedImageSource{ + Ref: "", + }, + }, + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonAvailable, + }, + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonSucceeded, + }, + }, + }, + }, + expectedCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "catalog", + Finalizers: []string{}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + AvailabilityMode: catalogdv1.AvailabilityModeUnavailable, + }, + Status: catalogdv1.ClusterCatalogStatus{ + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionFalse, + Reason: catalogdv1.ReasonUserSpecifiedUnavailable, + }, + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonSucceeded, + }, + }, + }, + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + reconciler := &ClusterCatalogReconciler{ + Client: nil, + Unpacker: tt.source, + Storage: tt.store, + storedCatalogs: map[string]storedCatalogData{}, + } + require.NoError(t, reconciler.setupFinalizers()) + ctx := context.Background() + + if tt.shouldPanic { + assert.Panics(t, func() { _, _ = reconciler.reconcile(ctx, tt.catalog) }) + return + } + + res, err := reconciler.reconcile(ctx, tt.catalog) + assert.Equal(t, ctrl.Result{}, res) + // errors are aggregated/wrapped + if tt.expectedError == nil { + require.NoError(t, err) + } else { + require.Error(t, err) + assert.Equal(t, tt.expectedError.Error(), err.Error()) + } + diff := cmp.Diff(tt.expectedCatalog, tt.catalog, + cmpopts.IgnoreFields(metav1.Condition{}, "Message", "LastTransitionTime"), + cmpopts.SortSlices(func(a, b metav1.Condition) bool { return a.Type < b.Type })) + assert.Empty(t, diff, "comparing the expected Catalog") + }) + } +} + +func TestPollingRequeue(t *testing.T) { + for name, tc := range map[string]struct { + catalog *catalogdv1.ClusterCatalog + expectedRequeueAfter time.Duration + lastPollTime metav1.Time + }{ + "ClusterCatalog with tag based image ref without any poll interval specified, requeueAfter set to 0, ie polling disabled": { + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + }, + expectedRequeueAfter: time.Second * 0, + lastPollTime: metav1.Now(), + }, + "ClusterCatalog with tag based image ref with poll interval specified, requeueAfter set to wait.jitter(pollInterval)": { + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + PollIntervalMinutes: ptr.To(5), + }, + }, + }, + }, + expectedRequeueAfter: time.Minute * 5, + lastPollTime: metav1.Now(), + }, + } { + t.Run(name, func(t *testing.T) { + reconciler := &ClusterCatalogReconciler{ + Client: nil, + Unpacker: &MockSource{result: &source.Result{ + State: source.StateUnpacked, + FS: &fstest.MapFS{}, + ResolvedSource: &catalogdv1.ResolvedCatalogSource{ + Image: &catalogdv1.ResolvedImageSource{ + Ref: "my.org/someImage@someSHA256Digest", + }, + }, + LastSuccessfulPollAttempt: tc.lastPollTime, + }}, + Storage: &MockStore{}, + storedCatalogs: map[string]storedCatalogData{}, + } + require.NoError(t, reconciler.setupFinalizers()) + res, _ := reconciler.reconcile(context.Background(), tc.catalog) + assert.InDelta(t, tc.expectedRequeueAfter, res.RequeueAfter, requeueJitterMaxFactor*float64(tc.expectedRequeueAfter)) + }) + } +} + +func TestPollingReconcilerUnpack(t *testing.T) { + oldDigest := "a5d4f4467250074216eb1ba1c36e06a3ab797d81c431427fc2aca97ecaf4e9d8" + newDigest := "f42337e7b85a46d83c94694638e2312e10ca16a03542399a65ba783c94a32b63" + + successfulObservedGeneration := int64(2) + successfulUnpackStatus := func(mods ...func(status *catalogdv1.ClusterCatalogStatus)) catalogdv1.ClusterCatalogStatus { + s := catalogdv1.ClusterCatalogStatus{ + URLs: &catalogdv1.ClusterCatalogURLs{Base: "URL"}, + Conditions: []metav1.Condition{ + { + Type: catalogdv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonSucceeded, + Message: "Successfully unpacked and stored content from resolved source", + ObservedGeneration: successfulObservedGeneration, + }, + { + Type: catalogdv1.TypeServing, + Status: metav1.ConditionTrue, + Reason: catalogdv1.ReasonAvailable, + Message: "Serving desired content from resolved source", + ObservedGeneration: successfulObservedGeneration, + }, + }, + ResolvedSource: &catalogdv1.ResolvedCatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ResolvedImageSource{ + Ref: "my.org/someimage@sha256:" + oldDigest, + }, + }, + LastUnpacked: &metav1.Time{}, + } + for _, mod := range mods { + mod(&s) + } + return s + } + successfulStoredCatalogData := func(lastPoll metav1.Time) map[string]storedCatalogData { + return map[string]storedCatalogData{ + "test-catalog": { + observedGeneration: successfulObservedGeneration, + unpackResult: source.Result{ + ResolvedSource: successfulUnpackStatus().ResolvedSource, + LastSuccessfulPollAttempt: lastPoll, + }, + }, + } + } + + for name, tc := range map[string]struct { + catalog *catalogdv1.ClusterCatalog + storedCatalogData map[string]storedCatalogData + expectedUnpackRun bool + }{ + "ClusterCatalog being resolved the first time, unpack should run": { + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Finalizers: []string{fbcDeletionFinalizer}, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + PollIntervalMinutes: ptr.To(5), + }, + }, + }, + }, + expectedUnpackRun: true, + }, + "ClusterCatalog not being resolved the first time, no pollInterval mentioned, unpack should not run": { + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Finalizers: []string{fbcDeletionFinalizer}, + Generation: 2, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + }, + }, + }, + Status: successfulUnpackStatus(), + }, + storedCatalogData: successfulStoredCatalogData(metav1.Now()), + expectedUnpackRun: false, + }, + "ClusterCatalog not being resolved the first time, pollInterval mentioned, \"now\" is before next expected poll time, unpack should not run": { + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Finalizers: []string{fbcDeletionFinalizer}, + Generation: 2, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + PollIntervalMinutes: ptr.To(7), + }, + }, + }, + Status: successfulUnpackStatus(), + }, + storedCatalogData: successfulStoredCatalogData(metav1.Now()), + expectedUnpackRun: false, + }, + "ClusterCatalog not being resolved the first time, pollInterval mentioned, \"now\" is after next expected poll time, unpack should run": { + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Finalizers: []string{fbcDeletionFinalizer}, + Generation: 2, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someimage:latest", + PollIntervalMinutes: ptr.To(3), + }, + }, + }, + Status: successfulUnpackStatus(), + }, + storedCatalogData: successfulStoredCatalogData(metav1.NewTime(time.Now().Add(-5 * time.Minute))), + expectedUnpackRun: true, + }, + "ClusterCatalog not being resolved the first time, pollInterval mentioned, \"now\" is before next expected poll time, generation changed, unpack should run": { + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Finalizers: []string{fbcDeletionFinalizer}, + Generation: 3, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someotherimage@sha256:" + newDigest, + PollIntervalMinutes: ptr.To(7), + }, + }, + }, + Status: successfulUnpackStatus(), + }, + storedCatalogData: successfulStoredCatalogData(metav1.Now()), + expectedUnpackRun: true, + }, + "ClusterCatalog not being resolved the first time, no stored catalog in cache, unpack should run": { + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Finalizers: []string{fbcDeletionFinalizer}, + Generation: 3, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someotherimage@sha256:" + newDigest, + PollIntervalMinutes: ptr.To(7), + }, + }, + }, + Status: successfulUnpackStatus(), + }, + expectedUnpackRun: true, + }, + "ClusterCatalog not being resolved the first time, unexpected status, unpack should run": { + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Finalizers: []string{fbcDeletionFinalizer}, + Generation: 3, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "my.org/someotherimage@sha256:" + newDigest, + PollIntervalMinutes: ptr.To(7), + }, + }, + }, + Status: successfulUnpackStatus(func(status *catalogdv1.ClusterCatalogStatus) { + meta.FindStatusCondition(status.Conditions, catalogdv1.TypeProgressing).Status = metav1.ConditionTrue + }), + }, + storedCatalogData: successfulStoredCatalogData(metav1.Now()), + expectedUnpackRun: true, + }, + } { + t.Run(name, func(t *testing.T) { + scd := tc.storedCatalogData + if scd == nil { + scd = map[string]storedCatalogData{} + } + reconciler := &ClusterCatalogReconciler{ + Client: nil, + Unpacker: &MockSource{unpackError: errors.New("mocksource error")}, + Storage: &MockStore{}, + storedCatalogs: scd, + } + require.NoError(t, reconciler.setupFinalizers()) + _, err := reconciler.reconcile(context.Background(), tc.catalog) + if tc.expectedUnpackRun { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} diff --git a/catalogd/internal/controllers/core/pull_secret_controller.go b/catalogd/internal/controllers/core/pull_secret_controller.go new file mode 100644 index 000000000..0255309ca --- /dev/null +++ b/catalogd/internal/controllers/core/pull_secret_controller.go @@ -0,0 +1,110 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package core + +import ( + "context" + "fmt" + "os" + + "github.com/go-logr/logr" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" +) + +// PullSecretReconciler reconciles a specific Secret object +// that contains global pull secrets for pulling Catalog images +type PullSecretReconciler struct { + client.Client + SecretKey types.NamespacedName + AuthFilePath string +} + +func (r *PullSecretReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + logger := log.FromContext(ctx) + if req.Name != r.SecretKey.Name || req.Namespace != r.SecretKey.Namespace { + logger.Error(fmt.Errorf("received unexpected request for Secret %v/%v", req.Namespace, req.Name), "reconciliation error") + return ctrl.Result{}, nil + } + + secret := &corev1.Secret{} + err := r.Get(ctx, req.NamespacedName, secret) + if err != nil { + if apierrors.IsNotFound(err) { + logger.Info("secret not found") + return r.deleteSecretFile(logger) + } + logger.Error(err, "failed to get Secret") + return ctrl.Result{}, err + } + + return r.writeSecretToFile(logger, secret) +} + +// SetupWithManager sets up the controller with the Manager. +func (r *PullSecretReconciler) SetupWithManager(mgr ctrl.Manager) error { + _, err := ctrl.NewControllerManagedBy(mgr). + For(&corev1.Secret{}). + WithEventFilter(newSecretPredicate(r.SecretKey)). + Build(r) + + return err +} + +func newSecretPredicate(key types.NamespacedName) predicate.Predicate { + return predicate.NewPredicateFuncs(func(obj client.Object) bool { + return obj.GetName() == key.Name && obj.GetNamespace() == key.Namespace + }) +} + +// writeSecretToFile writes the secret data to the specified file +func (r *PullSecretReconciler) writeSecretToFile(logger logr.Logger, secret *corev1.Secret) (ctrl.Result, error) { + // image registry secrets are always stored with the key .dockerconfigjson + // ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#registry-secret-existing-credentials + dockerConfigJSON, ok := secret.Data[".dockerconfigjson"] + if !ok { + logger.Error(fmt.Errorf("expected secret.Data key not found"), "expected secret Data to contain key .dockerconfigjson") + return ctrl.Result{}, nil + } + // expected format for auth.json + // https://github.com/containers/image/blob/main/docs/containers-auth.json.5.md + err := os.WriteFile(r.AuthFilePath, dockerConfigJSON, 0600) + if err != nil { + return ctrl.Result{}, fmt.Errorf("failed to write secret data to file: %w", err) + } + logger.Info("saved global pull secret data locally") + return ctrl.Result{}, nil +} + +// deleteSecretFile deletes the auth file if the secret is deleted +func (r *PullSecretReconciler) deleteSecretFile(logger logr.Logger) (ctrl.Result, error) { + logger.Info("deleting local auth file", "file", r.AuthFilePath) + if err := os.Remove(r.AuthFilePath); err != nil { + if os.IsNotExist(err) { + logger.Info("auth file does not exist, nothing to delete") + return ctrl.Result{}, nil + } + return ctrl.Result{}, fmt.Errorf("failed to delete secret file: %w", err) + } + logger.Info("auth file deleted successfully") + return ctrl.Result{}, nil +} diff --git a/catalogd/internal/controllers/core/pull_secret_controller_test.go b/catalogd/internal/controllers/core/pull_secret_controller_test.go new file mode 100644 index 000000000..8b91da340 --- /dev/null +++ b/catalogd/internal/controllers/core/pull_secret_controller_test.go @@ -0,0 +1,95 @@ +package core + +import ( + "context" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func TestSecretSyncerReconciler(t *testing.T) { + secretData := []byte(`{"auths":{"exampleRegistry": "exampledata"}}`) + authFileName := "test-auth.json" + for _, tt := range []struct { + name string + secret *corev1.Secret + addSecret bool + wantErr string + fileShouldExistBefore bool + fileShouldExistAfter bool + }{ + { + name: "secret exists, content gets saved to authFile", + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-secret", + Namespace: "test-secret-namespace", + }, + Data: map[string][]byte{ + ".dockerconfigjson": secretData, + }, + }, + addSecret: true, + fileShouldExistBefore: false, + fileShouldExistAfter: true, + }, + { + name: "secret does not exist, file exists previously, file should get deleted", + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-secret", + Namespace: "test-secret-namespace", + }, + Data: map[string][]byte{ + ".dockerconfigjson": secretData, + }, + }, + addSecret: false, + fileShouldExistBefore: true, + fileShouldExistAfter: false, + }, + } { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + tempAuthFile := filepath.Join(t.TempDir(), authFileName) + clientBuilder := fake.NewClientBuilder() + if tt.addSecret { + clientBuilder = clientBuilder.WithObjects(tt.secret) + } + cl := clientBuilder.Build() + + secretKey := types.NamespacedName{Namespace: tt.secret.Namespace, Name: tt.secret.Name} + r := &PullSecretReconciler{ + Client: cl, + SecretKey: secretKey, + AuthFilePath: tempAuthFile, + } + if tt.fileShouldExistBefore { + err := os.WriteFile(tempAuthFile, secretData, 0600) + require.NoError(t, err) + } + res, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: secretKey}) + if tt.wantErr == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, tt.wantErr) + } + require.Equal(t, ctrl.Result{}, res) + + if tt.fileShouldExistAfter { + _, err := os.Stat(tempAuthFile) + require.NoError(t, err) + } else { + _, err := os.Stat(tempAuthFile) + require.True(t, os.IsNotExist(err)) + } + }) + } +} diff --git a/catalogd/internal/features/features.go b/catalogd/internal/features/features.go new file mode 100644 index 000000000..8f67b1689 --- /dev/null +++ b/catalogd/internal/features/features.go @@ -0,0 +1,14 @@ +package features + +import ( + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/component-base/featuregate" +) + +var catalogdFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{} + +var CatalogdFeatureGate featuregate.MutableFeatureGate = featuregate.NewFeatureGate() + +func init() { + utilruntime.Must(CatalogdFeatureGate.Add(catalogdFeatureGates)) +} diff --git a/catalogd/internal/garbagecollection/garbage_collector.go b/catalogd/internal/garbagecollection/garbage_collector.go new file mode 100644 index 000000000..9a021dc9d --- /dev/null +++ b/catalogd/internal/garbagecollection/garbage_collector.go @@ -0,0 +1,94 @@ +package garbagecollection + +import ( + "context" + "fmt" + "os" + "path/filepath" + "time" + + "github.com/go-logr/logr" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/metadata" + "sigs.k8s.io/controller-runtime/pkg/manager" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" +) + +var _ manager.Runnable = (*GarbageCollector)(nil) + +// GarbageCollector is an implementation of the manager.Runnable +// interface for running garbage collection on the Catalog content +// cache that is served by the catalogd HTTP server. It runs in a loop +// and will ensure that no cache entries exist for Catalog resources +// that no longer exist. This should only clean up cache entries that +// were missed by the handling of a DELETE event on a Catalog resource. +type GarbageCollector struct { + CachePath string + Logger logr.Logger + MetadataClient metadata.Interface + Interval time.Duration +} + +// Start will start the garbage collector. It will always run once on startup +// and loop until context is canceled after an initial garbage collection run. +// Garbage collection will run again every X amount of time, where X is the +// supplied garbage collection interval. +func (gc *GarbageCollector) Start(ctx context.Context) error { + // Run once on startup + removed, err := runGarbageCollection(ctx, gc.CachePath, gc.MetadataClient) + if err != nil { + gc.Logger.Error(err, "running garbage collection") + } + if len(removed) > 0 { + gc.Logger.Info("removed stale cache entries", "removed entries", removed) + } + + // Loop until context is canceled, running garbage collection + // at the configured interval + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(gc.Interval): + removed, err := runGarbageCollection(ctx, gc.CachePath, gc.MetadataClient) + if err != nil { + gc.Logger.Error(err, "running garbage collection") + } + if len(removed) > 0 { + gc.Logger.Info("removed stale cache entries", "removed entries", removed) + } + } + } +} + +func runGarbageCollection(ctx context.Context, cachePath string, metaClient metadata.Interface) ([]string, error) { + getter := metaClient.Resource(catalogdv1.GroupVersion.WithResource("clustercatalogs")) + metaList, err := getter.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("error listing clustercatalogs: %w", err) + } + + expectedCatalogs := sets.New[string]() + for _, meta := range metaList.Items { + expectedCatalogs.Insert(meta.GetName()) + } + + cacheDirEntries, err := os.ReadDir(cachePath) + if err != nil { + return nil, fmt.Errorf("error reading cache directory: %w", err) + } + removed := []string{} + for _, cacheDirEntry := range cacheDirEntries { + if cacheDirEntry.IsDir() && expectedCatalogs.Has(cacheDirEntry.Name()) { + continue + } + if err := os.RemoveAll(filepath.Join(cachePath, cacheDirEntry.Name())); err != nil { + return nil, fmt.Errorf("error removing cache directory entry %q: %w ", cacheDirEntry.Name(), err) + } + + removed = append(removed, cacheDirEntry.Name()) + } + return removed, nil +} diff --git a/catalogd/internal/garbagecollection/garbage_collector_test.go b/catalogd/internal/garbagecollection/garbage_collector_test.go new file mode 100644 index 000000000..9210278d0 --- /dev/null +++ b/catalogd/internal/garbagecollection/garbage_collector_test.go @@ -0,0 +1,96 @@ +package garbagecollection + +import ( + "context" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/metadata/fake" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" +) + +func TestRunGarbageCollection(t *testing.T) { + for _, tt := range []struct { + name string + existCatalogs []*metav1.PartialObjectMetadata + notExistCatalogs []*metav1.PartialObjectMetadata + wantErr bool + }{ + { + name: "successful garbage collection", + existCatalogs: []*metav1.PartialObjectMetadata{ + { + TypeMeta: metav1.TypeMeta{ + Kind: "ClusterCatalog", + APIVersion: catalogdv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "one", + }, + }, + { + TypeMeta: metav1.TypeMeta{ + Kind: "ClusterCatalog", + APIVersion: catalogdv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "two", + }, + }, + }, + notExistCatalogs: []*metav1.PartialObjectMetadata{ + { + TypeMeta: metav1.TypeMeta{ + Kind: "ClusterCatalog", + APIVersion: catalogdv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "three", + }, + }, + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + cachePath := t.TempDir() + scheme := runtime.NewScheme() + require.NoError(t, metav1.AddMetaToScheme(scheme)) + + allCatalogs := append(tt.existCatalogs, tt.notExistCatalogs...) + for _, catalog := range allCatalogs { + require.NoError(t, os.MkdirAll(filepath.Join(cachePath, catalog.Name, "fakedigest"), os.ModePerm)) + } + + runtimeObjs := []runtime.Object{} + for _, catalog := range tt.existCatalogs { + runtimeObjs = append(runtimeObjs, catalog) + } + + metaClient := fake.NewSimpleMetadataClient(scheme, runtimeObjs...) + + _, err := runGarbageCollection(ctx, cachePath, metaClient) + if !tt.wantErr { + require.NoError(t, err) + entries, err := os.ReadDir(cachePath) + require.NoError(t, err) + assert.Len(t, entries, len(tt.existCatalogs)) + for _, catalog := range tt.existCatalogs { + assert.DirExists(t, filepath.Join(cachePath, catalog.Name)) + } + + for _, catalog := range tt.notExistCatalogs { + assert.NoDirExists(t, filepath.Join(cachePath, catalog.Name)) + } + } else { + assert.Error(t, err) + } + }) + } +} diff --git a/catalogd/internal/k8sutil/k8sutil.go b/catalogd/internal/k8sutil/k8sutil.go new file mode 100644 index 000000000..dfea1d0d6 --- /dev/null +++ b/catalogd/internal/k8sutil/k8sutil.go @@ -0,0 +1,17 @@ +package k8sutil + +import ( + "regexp" + + "k8s.io/apimachinery/pkg/util/validation" +) + +var invalidNameChars = regexp.MustCompile(`[^\.\-a-zA-Z0-9]`) + +// MetadataName replaces all invalid DNS characters with a dash. If the result +// is not a valid DNS subdomain, returns `result, false`. Otherwise, returns the +// `result, true`. +func MetadataName(name string) (string, bool) { + result := invalidNameChars.ReplaceAllString(name, "-") + return result, validation.IsDNS1123Subdomain(result) == nil +} diff --git a/catalogd/internal/k8sutil/k8sutil_test.go b/catalogd/internal/k8sutil/k8sutil_test.go new file mode 100644 index 000000000..d1b142680 --- /dev/null +++ b/catalogd/internal/k8sutil/k8sutil_test.go @@ -0,0 +1,62 @@ +package k8sutil + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMetadataName(t *testing.T) { + type testCase struct { + name string + in string + expectedResult string + expectedValid bool + } + for _, tc := range []testCase{ + { + name: "empty", + in: "", + expectedResult: "", + expectedValid: false, + }, + { + name: "invalid", + in: "foo-bar.123!", + expectedResult: "foo-bar.123-", + expectedValid: false, + }, + { + name: "too long", + in: fmt.Sprintf("foo-bar_%s", strings.Repeat("1234567890", 50)), + expectedResult: fmt.Sprintf("foo-bar-%s", strings.Repeat("1234567890", 50)), + expectedValid: false, + }, + { + name: "valid", + in: "foo-bar.123", + expectedResult: "foo-bar.123", + expectedValid: true, + }, + { + name: "valid with underscore", + in: "foo-bar_123", + expectedResult: "foo-bar-123", + expectedValid: true, + }, + { + name: "valid with colon", + in: "foo-bar:123", + expectedResult: "foo-bar-123", + expectedValid: true, + }, + } { + t.Run(tc.name, func(t *testing.T) { + actualResult, actualValid := MetadataName(tc.in) + assert.Equal(t, tc.expectedResult, actualResult) + assert.Equal(t, tc.expectedValid, actualValid) + }) + } +} diff --git a/catalogd/internal/metrics/metrics.go b/catalogd/internal/metrics/metrics.go new file mode 100644 index 000000000..c30aed584 --- /dev/null +++ b/catalogd/internal/metrics/metrics.go @@ -0,0 +1,40 @@ +package metrics + +import ( + "net/http" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +const ( + RequestDurationMetricName = "catalogd_http_request_duration_seconds" +) + +// Sets up the necessary metrics for calculating the Apdex Score +// If using Grafana for visualization connected to a Prometheus data +// source that is scraping these metrics, you can create a panel that +// uses the following queries + expressions for calculating the Apdex Score where T = 0.5: +// Query A: sum(catalogd_http_request_duration_seconds_bucket{code!~"5..",le="0.5"}) +// Query B: sum(catalogd_http_request_duration_seconds_bucket{code!~"5..",le="2"}) +// Query C: sum(catalogd_http_request_duration_seconds_count) +// Expression for Apdex Score: ($A + (($B - $A) / 2)) / $C +var ( + RequestDurationMetric = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Name: RequestDurationMetricName, + Help: "Histogram of request duration in seconds", + // create a bucket for each 100 ms up to 1s and ensure it multiplied by 4 also exists. + // Include a 10s bucket to capture very long running requests. This allows us to easily + // calculate Apdex Scores up to a T of 1 second, but using various mathmatical formulas we + // should be able to estimate Apdex Scores up to a T of 2.5. Having a larger range of buckets + // will allow us to more easily calculate health indicators other than the Apdex Score. + Buckets: []float64{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.6, 2, 2.4, 2.8, 3.2, 3.6, 4, 10}, + }, + []string{"code"}, + ) +) + +func AddMetricsToHandler(handler http.Handler) http.Handler { + return promhttp.InstrumentHandlerDuration(RequestDurationMetric, handler) +} diff --git a/catalogd/internal/serverutil/serverutil.go b/catalogd/internal/serverutil/serverutil.go new file mode 100644 index 000000000..b91225335 --- /dev/null +++ b/catalogd/internal/serverutil/serverutil.go @@ -0,0 +1,63 @@ +package serverutil + +import ( + "crypto/tls" + "fmt" + "net" + "net/http" + "time" + + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/certwatcher" + + catalogdmetrics "github.com/operator-framework/operator-controller/catalogd/internal/metrics" + "github.com/operator-framework/operator-controller/catalogd/internal/storage" + "github.com/operator-framework/operator-controller/catalogd/internal/third_party/server" +) + +type CatalogServerConfig struct { + ExternalAddr string + CatalogAddr string + CertFile string + KeyFile string + LocalStorage storage.Instance +} + +func AddCatalogServerToManager(mgr ctrl.Manager, cfg CatalogServerConfig, tlsFileWatcher *certwatcher.CertWatcher) error { + listener, err := net.Listen("tcp", cfg.CatalogAddr) + if err != nil { + return fmt.Errorf("error creating catalog server listener: %w", err) + } + + if cfg.CertFile != "" && cfg.KeyFile != "" { + // Use the passed certificate watcher instead of creating a new one + config := &tls.Config{ + GetCertificate: tlsFileWatcher.GetCertificate, + MinVersion: tls.VersionTLS12, + } + listener = tls.NewListener(listener, config) + } + + shutdownTimeout := 30 * time.Second + + catalogServer := server.Server{ + Kind: "catalogs", + Server: &http.Server{ + Addr: cfg.CatalogAddr, + Handler: catalogdmetrics.AddMetricsToHandler(cfg.LocalStorage.StorageServerHandler()), + ReadTimeout: 5 * time.Second, + // TODO: Revert this to 10 seconds if/when the API + // evolves to have significantly smaller responses + WriteTimeout: 5 * time.Minute, + }, + ShutdownTimeout: &shutdownTimeout, + Listener: listener, + } + + err = mgr.Add(&catalogServer) + if err != nil { + return fmt.Errorf("error adding catalog server to manager: %w", err) + } + + return nil +} diff --git a/catalogd/internal/source/containers_image.go b/catalogd/internal/source/containers_image.go new file mode 100644 index 000000000..c00db5c0f --- /dev/null +++ b/catalogd/internal/source/containers_image.go @@ -0,0 +1,425 @@ +package source + +import ( + "archive/tar" + "context" + "errors" + "fmt" + "io" + "os" + "path" + "path/filepath" + "strings" + "time" + + "github.com/containerd/containerd/archive" + "github.com/containers/image/v5/copy" + "github.com/containers/image/v5/docker" + "github.com/containers/image/v5/docker/reference" + "github.com/containers/image/v5/manifest" + "github.com/containers/image/v5/oci/layout" + "github.com/containers/image/v5/pkg/blobinfocache/none" + "github.com/containers/image/v5/pkg/compression" + "github.com/containers/image/v5/signature" + "github.com/containers/image/v5/types" + "github.com/go-logr/logr" + "github.com/opencontainers/go-digest" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" +) + +const ConfigDirLabel = "operators.operatorframework.io.index.configs.v1" + +type ContainersImageRegistry struct { + BaseCachePath string + SourceContextFunc func(logger logr.Logger) (*types.SystemContext, error) +} + +func (i *ContainersImageRegistry) Unpack(ctx context.Context, catalog *catalogdv1.ClusterCatalog) (*Result, error) { + l := log.FromContext(ctx) + + if catalog.Spec.Source.Type != catalogdv1.SourceTypeImage { + panic(fmt.Sprintf("programmer error: source type %q is unable to handle specified catalog source type %q", catalogdv1.SourceTypeImage, catalog.Spec.Source.Type)) + } + + if catalog.Spec.Source.Image == nil { + return nil, reconcile.TerminalError(fmt.Errorf("error parsing catalog, catalog %s has a nil image source", catalog.Name)) + } + + srcCtx, err := i.SourceContextFunc(l) + if err != nil { + return nil, err + } + ////////////////////////////////////////////////////// + // + // Resolve a canonical reference for the image. + // + ////////////////////////////////////////////////////// + imgRef, canonicalRef, specIsCanonical, err := resolveReferences(ctx, catalog.Spec.Source.Image.Ref, srcCtx) + if err != nil { + return nil, err + } + + ////////////////////////////////////////////////////// + // + // Check if the image is already unpacked. If it is, + // return the unpacked directory. + // + ////////////////////////////////////////////////////// + unpackPath := i.unpackPath(catalog.Name, canonicalRef.Digest()) + if unpackStat, err := os.Stat(unpackPath); err == nil { + if !unpackStat.IsDir() { + panic(fmt.Sprintf("unexpected file at unpack path %q: expected a directory", unpackPath)) + } + l.Info("image already unpacked", "ref", imgRef.String(), "digest", canonicalRef.Digest().String()) + return successResult(unpackPath, canonicalRef, unpackStat.ModTime()), nil + } + + ////////////////////////////////////////////////////// + // + // Create a docker reference for the source and an OCI + // layout reference for the destination, where we will + // temporarily store the image in order to unpack it. + // + // We use the OCI layout as a temporary storage because + // copy.Image can concurrently pull all the layers. + // + ////////////////////////////////////////////////////// + dockerRef, err := docker.NewReference(imgRef) + if err != nil { + return nil, fmt.Errorf("error creating source reference: %w", err) + } + + layoutDir, err := os.MkdirTemp("", fmt.Sprintf("oci-layout-%s", catalog.Name)) + if err != nil { + return nil, fmt.Errorf("error creating temporary directory: %w", err) + } + defer func() { + if err := os.RemoveAll(layoutDir); err != nil { + l.Error(err, "error removing temporary OCI layout directory") + } + }() + + layoutRef, err := layout.NewReference(layoutDir, canonicalRef.String()) + if err != nil { + return nil, fmt.Errorf("error creating reference: %w", err) + } + + ////////////////////////////////////////////////////// + // + // Load an image signature policy and build + // a policy context for the image pull. + // + ////////////////////////////////////////////////////// + policyContext, err := loadPolicyContext(srcCtx, l) + if err != nil { + return nil, fmt.Errorf("error loading policy context: %w", err) + } + defer func() { + if err := policyContext.Destroy(); err != nil { + l.Error(err, "error destroying policy context") + } + }() + + ////////////////////////////////////////////////////// + // + // Pull the image from the source to the destination + // + ////////////////////////////////////////////////////// + if _, err := copy.Image(ctx, policyContext, layoutRef, dockerRef, ©.Options{ + SourceCtx: srcCtx, + // We use the OCI layout as a temporary storage and + // pushing signatures for OCI images is not supported + // so we remove the source signatures when copying. + // Signature validation will still be performed + // accordingly to a provided policy context. + RemoveSignatures: true, + }); err != nil { + return nil, fmt.Errorf("error copying image: %w", err) + } + l.Info("pulled image", "ref", imgRef.String(), "digest", canonicalRef.Digest().String()) + + ////////////////////////////////////////////////////// + // + // Mount the image we just pulled + // + ////////////////////////////////////////////////////// + if err := i.unpackImage(ctx, unpackPath, layoutRef, specIsCanonical, srcCtx); err != nil { + if cleanupErr := deleteRecursive(unpackPath); cleanupErr != nil { + err = errors.Join(err, cleanupErr) + } + return nil, fmt.Errorf("error unpacking image: %w", err) + } + + ////////////////////////////////////////////////////// + // + // Delete other images. They are no longer needed. + // + ////////////////////////////////////////////////////// + if err := i.deleteOtherImages(catalog.Name, canonicalRef.Digest()); err != nil { + return nil, fmt.Errorf("error deleting old images: %w", err) + } + + return successResult(unpackPath, canonicalRef, time.Now()), nil +} + +func successResult(unpackPath string, canonicalRef reference.Canonical, lastUnpacked time.Time) *Result { + return &Result{ + FS: os.DirFS(unpackPath), + ResolvedSource: &catalogdv1.ResolvedCatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ResolvedImageSource{ + Ref: canonicalRef.String(), + }, + }, + State: StateUnpacked, + Message: fmt.Sprintf("unpacked %q successfully", canonicalRef), + + // We truncate both the unpack time and last successful poll attempt + // to the second because metav1.Time is serialized + // as RFC 3339 which only has second-level precision. When we + // use this result in a comparison with what we deserialized + // from the Kubernetes API server, we need it to match. + UnpackTime: lastUnpacked.Truncate(time.Second), + LastSuccessfulPollAttempt: metav1.NewTime(time.Now().Truncate(time.Second)), + } +} + +func (i *ContainersImageRegistry) Cleanup(_ context.Context, catalog *catalogdv1.ClusterCatalog) error { + if err := deleteRecursive(i.catalogPath(catalog.Name)); err != nil { + return fmt.Errorf("error deleting catalog cache: %w", err) + } + return nil +} + +func (i *ContainersImageRegistry) catalogPath(catalogName string) string { + return filepath.Join(i.BaseCachePath, catalogName) +} + +func (i *ContainersImageRegistry) unpackPath(catalogName string, digest digest.Digest) string { + return filepath.Join(i.catalogPath(catalogName), digest.String()) +} + +func resolveReferences(ctx context.Context, ref string, sourceContext *types.SystemContext) (reference.Named, reference.Canonical, bool, error) { + imgRef, err := reference.ParseNamed(ref) + if err != nil { + return nil, nil, false, reconcile.TerminalError(fmt.Errorf("error parsing image reference %q: %w", ref, err)) + } + + canonicalRef, isCanonical, err := resolveCanonicalRef(ctx, imgRef, sourceContext) + if err != nil { + return nil, nil, false, fmt.Errorf("error resolving canonical reference: %w", err) + } + return imgRef, canonicalRef, isCanonical, nil +} + +func resolveCanonicalRef(ctx context.Context, imgRef reference.Named, imageCtx *types.SystemContext) (reference.Canonical, bool, error) { + if canonicalRef, ok := imgRef.(reference.Canonical); ok { + return canonicalRef, true, nil + } + + srcRef, err := docker.NewReference(imgRef) + if err != nil { + return nil, false, reconcile.TerminalError(fmt.Errorf("error creating reference: %w", err)) + } + + imgSrc, err := srcRef.NewImageSource(ctx, imageCtx) + if err != nil { + return nil, false, fmt.Errorf("error creating image source: %w", err) + } + defer imgSrc.Close() + + imgManifestData, _, err := imgSrc.GetManifest(ctx, nil) + if err != nil { + return nil, false, fmt.Errorf("error getting manifest: %w", err) + } + imgDigest, err := manifest.Digest(imgManifestData) + if err != nil { + return nil, false, fmt.Errorf("error getting digest of manifest: %w", err) + } + canonicalRef, err := reference.WithDigest(reference.TrimNamed(imgRef), imgDigest) + if err != nil { + return nil, false, fmt.Errorf("error creating canonical reference: %w", err) + } + return canonicalRef, false, nil +} + +func loadPolicyContext(sourceContext *types.SystemContext, l logr.Logger) (*signature.PolicyContext, error) { + policy, err := signature.DefaultPolicy(sourceContext) + if os.IsNotExist(err) { + l.Info("no default policy found, using insecure policy") + policy, err = signature.NewPolicyFromBytes([]byte(`{"default":[{"type":"insecureAcceptAnything"}]}`)) + } + if err != nil { + return nil, fmt.Errorf("error loading default policy: %w", err) + } + return signature.NewPolicyContext(policy) +} + +func (i *ContainersImageRegistry) unpackImage(ctx context.Context, unpackPath string, imageReference types.ImageReference, specIsCanonical bool, sourceContext *types.SystemContext) error { + img, err := imageReference.NewImage(ctx, sourceContext) + if err != nil { + return fmt.Errorf("error reading image: %w", err) + } + defer func() { + if err := img.Close(); err != nil { + panic(err) + } + }() + + layoutSrc, err := imageReference.NewImageSource(ctx, sourceContext) + if err != nil { + return fmt.Errorf("error creating image source: %w", err) + } + + cfg, err := img.OCIConfig(ctx) + if err != nil { + return fmt.Errorf("error parsing image config: %w", err) + } + + dirToUnpack, ok := cfg.Config.Labels[ConfigDirLabel] + if !ok { + // If the spec is a tagged ref, retries could end up resolving a new digest, where the label + // might show up. If the spec is canonical, no amount of retries will make the label appear. + // Therefore, we treat the error as terminal if the reference from the spec is canonical. + return wrapTerminal(fmt.Errorf("catalog image is missing the required label %q", ConfigDirLabel), specIsCanonical) + } + + if err := os.MkdirAll(unpackPath, 0700); err != nil { + return fmt.Errorf("error creating unpack directory: %w", err) + } + l := log.FromContext(ctx) + l.Info("unpacking image", "path", unpackPath) + for i, layerInfo := range img.LayerInfos() { + if err := func() error { + layerReader, _, err := layoutSrc.GetBlob(ctx, layerInfo, none.NoCache) + if err != nil { + return fmt.Errorf("error getting blob for layer[%d]: %w", i, err) + } + defer layerReader.Close() + + if err := applyLayer(ctx, unpackPath, dirToUnpack, layerReader); err != nil { + return fmt.Errorf("error applying layer[%d]: %w", i, err) + } + l.Info("applied layer", "layer", i) + return nil + }(); err != nil { + return errors.Join(err, deleteRecursive(unpackPath)) + } + } + if err := setReadOnlyRecursive(unpackPath); err != nil { + return fmt.Errorf("error making unpack directory read-only: %w", err) + } + return nil +} + +func applyLayer(ctx context.Context, destPath string, srcPath string, layer io.ReadCloser) error { + decompressed, _, err := compression.AutoDecompress(layer) + if err != nil { + return fmt.Errorf("auto-decompress failed: %w", err) + } + defer decompressed.Close() + + _, err = archive.Apply(ctx, destPath, decompressed, archive.WithFilter(applyLayerFilter(srcPath))) + return err +} + +func applyLayerFilter(srcPath string) archive.Filter { + cleanSrcPath := path.Clean(strings.TrimPrefix(srcPath, "/")) + return func(h *tar.Header) (bool, error) { + h.Uid = os.Getuid() + h.Gid = os.Getgid() + h.Mode |= 0700 + + cleanName := path.Clean(strings.TrimPrefix(h.Name, "/")) + relPath, err := filepath.Rel(cleanSrcPath, cleanName) + if err != nil { + return false, fmt.Errorf("error getting relative path: %w", err) + } + return relPath != ".." && !strings.HasPrefix(relPath, "../"), nil + } +} + +func (i *ContainersImageRegistry) deleteOtherImages(catalogName string, digestToKeep digest.Digest) error { + catalogPath := i.catalogPath(catalogName) + imgDirs, err := os.ReadDir(catalogPath) + if err != nil { + return fmt.Errorf("error reading image directories: %w", err) + } + for _, imgDir := range imgDirs { + if imgDir.Name() == digestToKeep.String() { + continue + } + imgDirPath := filepath.Join(catalogPath, imgDir.Name()) + if err := deleteRecursive(imgDirPath); err != nil { + return fmt.Errorf("error removing image directory: %w", err) + } + } + return nil +} + +func setReadOnlyRecursive(root string) error { + if err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error { + if err != nil { + return err + } + + fi, err := d.Info() + if err != nil { + return err + } + + if err := func() error { + switch typ := fi.Mode().Type(); typ { + case os.ModeSymlink: + // do not follow symlinks + // 1. if they resolve to other locations in the root, we'll find them anyway + // 2. if they resolve to other locations outside the root, we don't want to change their permissions + return nil + case os.ModeDir: + return os.Chmod(path, 0500) + case 0: // regular file + return os.Chmod(path, 0400) + default: + return fmt.Errorf("refusing to change ownership of file %q with type %v", path, typ.String()) + } + }(); err != nil { + return err + } + return nil + }); err != nil { + return fmt.Errorf("error making catalog cache read-only: %w", err) + } + return nil +} + +func deleteRecursive(root string) error { + if err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error { + if os.IsNotExist(err) { + return nil + } + if err != nil { + return err + } + if !d.IsDir() { + return nil + } + if err := os.Chmod(path, 0700); err != nil { + return err + } + return nil + }); err != nil { + return fmt.Errorf("error making catalog cache writable for deletion: %w", err) + } + return os.RemoveAll(root) +} + +func wrapTerminal(err error, isTerminal bool) error { + if !isTerminal { + return err + } + return reconcile.TerminalError(err) +} diff --git a/catalogd/internal/source/containers_image_internal_test.go b/catalogd/internal/source/containers_image_internal_test.go new file mode 100644 index 000000000..0c3ba1286 --- /dev/null +++ b/catalogd/internal/source/containers_image_internal_test.go @@ -0,0 +1,130 @@ +package source + +import ( + "archive/tar" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestContainersImage_applyLayerFilter(t *testing.T) { + type testCase struct { + name string + srcPaths []string + tarHeaders []tar.Header + assertion func(*tar.Header, bool, error) + } + for _, tc := range []testCase{ + { + name: "everything found when srcPaths represent root", + srcPaths: []string{"", "/"}, + tarHeaders: []tar.Header{ + { + Name: "file", + }, + { + Name: "/file", + }, + { + Name: "/nested/file", + }, + { + Name: "/deeply/nested/file", + }, + }, + assertion: func(tarHeader *tar.Header, keep bool, err error) { + assert.True(t, keep) + assert.NoError(t, err) + }, + }, + { + name: "nothing found outside of srcPath", + srcPaths: []string{"source"}, + tarHeaders: []tar.Header{ + { + Name: "elsewhere", + }, + { + Name: "/elsewhere", + }, + { + Name: "/nested/elsewhere", + }, + { + Name: "/deeply/nested/elsewhere", + }, + }, + assertion: func(tarHeader *tar.Header, keep bool, err error) { + assert.False(t, keep) + assert.NoError(t, err) + }, + }, + { + name: "absolute paths are trimmed", + srcPaths: []string{"source", "/source"}, + tarHeaders: []tar.Header{ + { + Name: "source", + }, + { + Name: "/source", + }, + { + Name: "source/nested/elsewhere", + }, + { + Name: "/source/nested/elsewhere", + }, + { + Name: "source/deeply/nested/elsewhere", + }, + { + Name: "/source/deeply/nested/elsewhere", + }, + }, + assertion: func(tarHeader *tar.Header, keep bool, err error) { + assert.True(t, keep) + assert.NoError(t, err) + }, + }, + { + name: "up level source paths are not supported", + srcPaths: []string{"../not-supported"}, + tarHeaders: []tar.Header{ + { + Name: "anything", + }, + }, + assertion: func(tarHeader *tar.Header, keep bool, err error) { + assert.False(t, keep) + assert.ErrorContains(t, err, "error getting relative path") + }, + }, + { + name: "up level tar headers are not supported", + srcPaths: []string{"fine"}, + tarHeaders: []tar.Header{ + { + Name: "../not-supported", + }, + { + Name: "../fine", + }, + }, + assertion: func(tarHeader *tar.Header, keep bool, err error) { + assert.False(t, keep) + assert.NoError(t, err) + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + for _, srcPath := range tc.srcPaths { + f := applyLayerFilter(srcPath) + for _, tarHeader := range tc.tarHeaders { + keep, err := f(&tarHeader) + tc.assertion(&tarHeader, keep, err) + } + } + }) + } +} diff --git a/catalogd/internal/source/containers_image_test.go b/catalogd/internal/source/containers_image_test.go new file mode 100644 index 000000000..138464cbe --- /dev/null +++ b/catalogd/internal/source/containers_image_test.go @@ -0,0 +1,477 @@ +package source_test + +import ( + "bytes" + "context" + "errors" + "fmt" + "net/http/httptest" + "net/url" + "os" + "path/filepath" + "testing" + "time" + + "github.com/containers/image/v5/types" + "github.com/go-logr/logr" + "github.com/go-logr/logr/funcr" + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/registry" + "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/mutate" + "github.com/google/go-containerregistry/pkg/v1/random" + "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" + "github.com/operator-framework/operator-controller/catalogd/internal/source" +) + +func TestImageRegistry(t *testing.T) { + for _, tt := range []struct { + name string + // catalog is the Catalog passed to the Unpack function. + // if the Catalog.Spec.Source.Image.Ref field is empty, + // one is injected during test runtime to ensure it + // points to the registry created for the test + catalog *catalogdv1.ClusterCatalog + wantErr bool + terminal bool + image v1.Image + digestAlreadyExists bool + oldDigestExists bool + // refType is the type of image ref this test + // is using. Should be one of "tag","digest" + refType string + }{ + { + name: ".spec.source.image is nil", + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: nil, + }, + }, + }, + wantErr: true, + terminal: true, + refType: "tag", + }, + { + name: ".spec.source.image.ref is unparsable", + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "::)12-as^&8asd789A(::", + }, + }, + }, + }, + wantErr: true, + terminal: true, + refType: "tag", + }, + { + name: "tag based, image is missing required label", + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "", + }, + }, + }, + }, + wantErr: true, + image: func() v1.Image { + img, err := random.Image(20, 3) + if err != nil { + panic(err) + } + return img + }(), + refType: "tag", + }, + { + name: "digest based, image is missing required label", + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "", + }, + }, + }, + }, + wantErr: true, + terminal: true, + image: func() v1.Image { + img, err := random.Image(20, 3) + if err != nil { + panic(err) + } + return img + }(), + refType: "digest", + }, + { + name: "image doesn't exist", + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "", + }, + }, + }, + }, + wantErr: true, + refType: "tag", + }, + { + name: "tag based image, digest already exists in cache", + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "", + }, + }, + }, + }, + wantErr: false, + image: func() v1.Image { + img, err := random.Image(20, 3) + if err != nil { + panic(err) + } + return img + }(), + digestAlreadyExists: true, + refType: "tag", + }, + { + name: "digest based image, digest already exists in cache", + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "", + }, + }, + }, + }, + wantErr: false, + digestAlreadyExists: true, + refType: "digest", + image: func() v1.Image { + img, err := random.Image(20, 3) + if err != nil { + panic(err) + } + return img + }(), + }, + { + name: "old ref is cached", + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "", + }, + }, + }, + }, + wantErr: false, + oldDigestExists: true, + refType: "tag", + image: func() v1.Image { + img, err := random.Image(20, 3) + if err != nil { + panic(err) + } + img, err = mutate.Config(img, v1.Config{ + Labels: map[string]string{ + source.ConfigDirLabel: "/configs", + }, + }) + if err != nil { + panic(err) + } + return img + }(), + }, + { + name: "tag ref, happy path", + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "", + }, + }, + }, + }, + wantErr: false, + refType: "tag", + image: func() v1.Image { + img, err := random.Image(20, 3) + if err != nil { + panic(err) + } + img, err = mutate.Config(img, v1.Config{ + Labels: map[string]string{ + source.ConfigDirLabel: "/configs", + }, + }) + if err != nil { + panic(err) + } + return img + }(), + }, + { + name: "digest ref, happy path", + catalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: "", + }, + }, + }, + }, + wantErr: false, + refType: "digest", + image: func() v1.Image { + img, err := random.Image(20, 3) + if err != nil { + panic(err) + } + img, err = mutate.Config(img, v1.Config{ + Labels: map[string]string{ + source.ConfigDirLabel: "/configs", + }, + }) + if err != nil { + panic(err) + } + return img + }(), + }, + } { + t.Run(tt.name, func(t *testing.T) { + // Create context, temporary cache directory, + // and image registry source + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + testCache := t.TempDir() + imgReg := &source.ContainersImageRegistry{ + BaseCachePath: testCache, + SourceContextFunc: func(logger logr.Logger) (*types.SystemContext, error) { + return &types.SystemContext{ + OCIInsecureSkipTLSVerify: true, + DockerInsecureSkipTLSVerify: types.OptionalBoolTrue, + }, nil + }, + } + + // Create a logger with a simple function-based LogSink that writes to the buffer + var buf bytes.Buffer + logger := funcr.New(func(prefix, args string) { + buf.WriteString(fmt.Sprintf("%s %s\n", prefix, args)) + }, funcr.Options{Verbosity: 1}) + + // Add the logger into the context which will later be used + // in the Unpack function to get the logger + ctx = log.IntoContext(ctx, logger) + + // Start a new server running an image registry + srv := httptest.NewServer(registry.New()) + defer srv.Close() + + // parse the server url so we can grab just the host + url, err := url.Parse(srv.URL) + require.NoError(t, err) + + // Build the proper image name with {registry}/tt.imgName + imgName, err := name.ParseReference(fmt.Sprintf("%s/%s", url.Host, "test-image:test")) + require.NoError(t, err) + + // If an old digest should exist in the cache, create one + oldDigestDir := filepath.Join(testCache, tt.catalog.Name, "olddigest") + var oldDigestModTime time.Time + if tt.oldDigestExists { + require.NoError(t, os.MkdirAll(oldDigestDir, os.ModePerm)) + oldDigestDirStat, err := os.Stat(oldDigestDir) + require.NoError(t, err) + oldDigestModTime = oldDigestDirStat.ModTime() + } + + var digest v1.Hash + // if the test specifies a method that returns a v1.Image, + // call it and push the image to the registry + if tt.image != nil { + digest, err = tt.image.Digest() + require.NoError(t, err) + + // if the digest should already exist in the cache, create it + if tt.digestAlreadyExists { + err = os.MkdirAll(filepath.Join(testCache, tt.catalog.Name, digest.String()), os.ModePerm) + require.NoError(t, err) + } + + err = remote.Write(imgName, tt.image) + require.NoError(t, err) + + // if the image ref should be a digest ref, make it so + if tt.refType == "digest" { + imgName, err = name.ParseReference(fmt.Sprintf("%s/%s", url.Host, "test-image@sha256:"+digest.Hex)) + require.NoError(t, err) + } + } + + // Inject the image reference if needed + if tt.catalog.Spec.Source.Image != nil && tt.catalog.Spec.Source.Image.Ref == "" { + tt.catalog.Spec.Source.Image.Ref = imgName.Name() + } + + rs, err := imgReg.Unpack(ctx, tt.catalog) + if !tt.wantErr { + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("%s@sha256:%s", imgName.Context().Name(), digest.Hex), rs.ResolvedSource.Image.Ref) + assert.Equal(t, source.StateUnpacked, rs.State) + + unpackDir := filepath.Join(testCache, tt.catalog.Name, digest.String()) + assert.DirExists(t, unpackDir) + unpackDirStat, err := os.Stat(unpackDir) + require.NoError(t, err) + + entries, err := os.ReadDir(filepath.Join(testCache, tt.catalog.Name)) + require.NoError(t, err) + assert.Len(t, entries, 1) + // If the digest should already exist check that we actually hit it + if tt.digestAlreadyExists { + assert.Contains(t, buf.String(), "image already unpacked") + assert.Equal(t, rs.UnpackTime, unpackDirStat.ModTime().Truncate(time.Second)) + } else if tt.oldDigestExists { + assert.NotContains(t, buf.String(), "image already unpacked") + assert.NotEqual(t, rs.UnpackTime, oldDigestModTime) + assert.NoDirExists(t, oldDigestDir) + } else { + require.NotNil(t, rs.UnpackTime) + require.NotNil(t, rs.ResolvedSource.Image) + assert.False(t, rs.UnpackTime.IsZero()) + } + } else { + require.Error(t, err) + isTerminal := errors.Is(err, reconcile.TerminalError(nil)) + assert.Equal(t, tt.terminal, isTerminal, "expected terminal %v, got %v", tt.terminal, isTerminal) + } + + assert.NoError(t, imgReg.Cleanup(ctx, tt.catalog)) + assert.NoError(t, imgReg.Cleanup(ctx, tt.catalog), "cleanup should ignore missing files") + }) + } +} + +// TestImageRegistryMissingLabelConsistentFailure is a test +// case that specifically tests that multiple calls to the +// ImageRegistry.Unpack() method return an error and is meant +// to ensure coverage of the bug reported in +// https://github.com/operator-framework/operator-controller/catalogd/issues/206 +func TestImageRegistryMissingLabelConsistentFailure(t *testing.T) { + // Create context, temporary cache directory, + // and image registry source + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + testCache := t.TempDir() + imgReg := &source.ContainersImageRegistry{ + BaseCachePath: testCache, + SourceContextFunc: func(logger logr.Logger) (*types.SystemContext, error) { + return &types.SystemContext{}, nil + }, + } + + // Start a new server running an image registry + srv := httptest.NewServer(registry.New()) + defer srv.Close() + + // parse the server url so we can grab just the host + url, err := url.Parse(srv.URL) + require.NoError(t, err) + + imgName, err := name.ParseReference(fmt.Sprintf("%s/%s", url.Host, "test-image:test")) + require.NoError(t, err) + + image, err := random.Image(20, 20) + require.NoError(t, err) + + err = remote.Write(imgName, image) + require.NoError(t, err) + + catalog := &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: imgName.Name(), + }, + }, + }, + } + + for i := 0; i < 3; i++ { + _, err = imgReg.Unpack(ctx, catalog) + require.Error(t, err, "unpack run ", i) + } +} diff --git a/catalogd/internal/source/unpacker.go b/catalogd/internal/source/unpacker.go new file mode 100644 index 000000000..f0bb2449c --- /dev/null +++ b/catalogd/internal/source/unpacker.go @@ -0,0 +1,72 @@ +package source + +import ( + "context" + "io/fs" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" +) + +// TODO: This package is almost entirely copy/pasted from rukpak. We should look +// into whether it is possible to share this code. +// +// TODO: None of the rukpak CRD validations (both static and from the rukpak +// webhooks) related to the source are present here. Which of them do we need? + +// Unpacker unpacks catalog content, either synchronously or asynchronously and +// returns a Result, which conveys information about the progress of unpacking +// the catalog content. +// +// If a Source unpacks content asynchronously, it should register one or more +// watches with a controller to ensure that Bundles referencing this source +// can be reconciled as progress updates are available. +// +// For asynchronous Sources, multiple calls to Unpack should be made until the +// returned result includes state StateUnpacked. +// +// NOTE: A source is meant to be agnostic to specific catalog formats and +// specifications. A source should treat a catalog root directory as an opaque +// file tree and delegate catalog format concerns to catalog parsers. +type Unpacker interface { + Unpack(context.Context, *catalogdv1.ClusterCatalog) (*Result, error) + Cleanup(context.Context, *catalogdv1.ClusterCatalog) error +} + +// Result conveys progress information about unpacking catalog content. +type Result struct { + // Bundle contains the full filesystem of a catalog's root directory. + FS fs.FS + + // ResolvedSource is a reproducible view of a Bundle's Source. + // When possible, source implementations should return a ResolvedSource + // that pins the Source such that future fetches of the catalog content can + // be guaranteed to fetch the exact same catalog content as the original + // unpack. + // + // For example, resolved image sources should reference a container image + // digest rather than an image tag, and git sources should reference a + // commit hash rather than a branch or tag. + ResolvedSource *catalogdv1.ResolvedCatalogSource + + LastSuccessfulPollAttempt metav1.Time + + // State is the current state of unpacking the catalog content. + State State + + // Message is contextual information about the progress of unpacking the + // catalog content. + Message string + + // UnpackTime is the timestamp when the transition to the current State happened + UnpackTime time.Time +} + +type State string + +// StateUnpacked conveys that the catalog has been successfully unpacked. +const StateUnpacked State = "Unpacked" + +const UnpackCacheDir = "unpack" diff --git a/catalogd/internal/storage/localdir.go b/catalogd/internal/storage/localdir.go new file mode 100644 index 000000000..dd06729ea --- /dev/null +++ b/catalogd/internal/storage/localdir.go @@ -0,0 +1,114 @@ +package storage + +import ( + "context" + "fmt" + "io/fs" + "net/http" + "net/url" + "os" + "path/filepath" + + "github.com/klauspost/compress/gzhttp" + + "github.com/operator-framework/operator-registry/alpha/declcfg" +) + +// LocalDirV1 is a storage Instance. When Storing a new FBC contained in +// fs.FS, the content is first written to a temporary file, after which +// it is copied to its final destination in RootDir/catalogName/. This is +// done so that clients accessing the content stored in RootDir/catalogName have +// atomic view of the content for a catalog. +type LocalDirV1 struct { + RootDir string + RootURL *url.URL +} + +const ( + v1ApiPath = "api/v1" + v1ApiData = "all" +) + +func (s LocalDirV1) Store(ctx context.Context, catalog string, fsys fs.FS) error { + fbcDir := filepath.Join(s.RootDir, catalog, v1ApiPath) + if err := os.MkdirAll(fbcDir, 0700); err != nil { + return err + } + tempFile, err := os.CreateTemp(s.RootDir, fmt.Sprint(catalog)) + if err != nil { + return err + } + defer os.Remove(tempFile.Name()) + if err := declcfg.WalkMetasFS(ctx, fsys, func(path string, meta *declcfg.Meta, err error) error { + if err != nil { + return err + } + _, err = tempFile.Write(meta.Blob) + return err + }); err != nil { + return fmt.Errorf("error walking FBC root: %w", err) + } + fbcFile := filepath.Join(fbcDir, v1ApiData) + return os.Rename(tempFile.Name(), fbcFile) +} + +func (s LocalDirV1) Delete(catalog string) error { + return os.RemoveAll(filepath.Join(s.RootDir, catalog)) +} + +func (s LocalDirV1) BaseURL(catalog string) string { + return s.RootURL.JoinPath(catalog).String() +} + +func (s LocalDirV1) StorageServerHandler() http.Handler { + mux := http.NewServeMux() + fsHandler := http.FileServer(http.FS(&filesOnlyFilesystem{os.DirFS(s.RootDir)})) + spHandler := http.StripPrefix(s.RootURL.Path, fsHandler) + gzHandler := gzhttp.GzipHandler(spHandler) + + typeHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Content-Type", "application/jsonl") + gzHandler.ServeHTTP(w, r) + }) + mux.Handle(s.RootURL.Path, typeHandler) + return mux +} + +func (s LocalDirV1) ContentExists(catalog string) bool { + file, err := os.Stat(filepath.Join(s.RootDir, catalog, v1ApiPath, v1ApiData)) + if err != nil { + return false + } + if !file.Mode().IsRegular() { + // path is not valid content + return false + } + return true +} + +// filesOnlyFilesystem is a file system that can open only regular +// files from the underlying filesystem. All other file types result +// in os.ErrNotExists +type filesOnlyFilesystem struct { + FS fs.FS +} + +// Open opens a named file from the underlying filesystem. If the file +// is not a regular file, it return os.ErrNotExists. Callers are resposible +// for closing the file returned. +func (f *filesOnlyFilesystem) Open(name string) (fs.File, error) { + file, err := f.FS.Open(name) + if err != nil { + return nil, err + } + stat, err := file.Stat() + if err != nil { + _ = file.Close() + return nil, err + } + if !stat.Mode().IsRegular() { + _ = file.Close() + return nil, os.ErrNotExist + } + return file, nil +} diff --git a/catalogd/internal/storage/localdir_test.go b/catalogd/internal/storage/localdir_test.go new file mode 100644 index 000000000..c975c8fc9 --- /dev/null +++ b/catalogd/internal/storage/localdir_test.go @@ -0,0 +1,438 @@ +package storage + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "io/fs" + "net/http" + "net/http/httptest" + "net/url" + "os" + "path/filepath" + "strings" + "testing/fstest" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/google/go-cmp/cmp" + "sigs.k8s.io/yaml" + + "github.com/operator-framework/operator-registry/alpha/declcfg" +) + +const urlPrefix = "/catalogs/" + +var ctx = context.Background() + +var _ = Describe("LocalDir Storage Test", func() { + var ( + catalog = "test-catalog" + store Instance + rootDir string + baseURL *url.URL + testBundleName = "bundle.v0.0.1" + testBundleImage = "quaydock.io/namespace/bundle:0.0.3" + testBundleRelatedImageName = "test" + testBundleRelatedImageImage = "testimage:latest" + testBundleObjectData = "dW5pbXBvcnRhbnQK" + testPackageDefaultChannel = "preview_test" + testPackageName = "webhook_operator_test" + testChannelName = "preview_test" + testPackage = fmt.Sprintf(testPackageTemplate, testPackageDefaultChannel, testPackageName) + testBundle = fmt.Sprintf(testBundleTemplate, testBundleImage, testBundleName, testPackageName, testBundleRelatedImageName, testBundleRelatedImageImage, testBundleObjectData) + testChannel = fmt.Sprintf(testChannelTemplate, testPackageName, testChannelName, testBundleName) + + unpackResultFS fs.FS + ) + BeforeEach(func() { + d, err := os.MkdirTemp(GinkgoT().TempDir(), "cache") + Expect(err).ToNot(HaveOccurred()) + rootDir = d + + baseURL = &url.URL{Scheme: "http", Host: "test-addr", Path: urlPrefix} + store = LocalDirV1{RootDir: rootDir, RootURL: baseURL} + unpackResultFS = &fstest.MapFS{ + "bundle.yaml": &fstest.MapFile{Data: []byte(testBundle), Mode: os.ModePerm}, + "package.yaml": &fstest.MapFile{Data: []byte(testPackage), Mode: os.ModePerm}, + "channel.yaml": &fstest.MapFile{Data: []byte(testChannel), Mode: os.ModePerm}, + } + }) + When("An unpacked FBC is stored using LocalDir", func() { + BeforeEach(func() { + err := store.Store(context.Background(), catalog, unpackResultFS) + Expect(err).To(Not(HaveOccurred())) + }) + It("should store the content in the RootDir correctly", func() { + fbcDir := filepath.Join(rootDir, catalog, v1ApiPath) + fbcFile := filepath.Join(fbcDir, v1ApiData) + _, err := os.Stat(fbcFile) + Expect(err).To(Not(HaveOccurred())) + + gotConfig, err := declcfg.LoadFS(ctx, unpackResultFS) + Expect(err).To(Not(HaveOccurred())) + storedConfig, err := declcfg.LoadFile(os.DirFS(fbcDir), v1ApiData) + Expect(err).To(Not(HaveOccurred())) + diff := cmp.Diff(gotConfig, storedConfig) + Expect(diff).To(Equal("")) + }) + It("should form the content URL correctly", func() { + Expect(store.BaseURL(catalog)).To(Equal(baseURL.JoinPath(catalog).String())) + }) + It("should report content exists", func() { + Expect(store.ContentExists(catalog)).To(BeTrue()) + }) + When("The stored content is deleted", func() { + BeforeEach(func() { + err := store.Delete(catalog) + Expect(err).To(Not(HaveOccurred())) + }) + It("should delete the FBC from the cache directory", func() { + fbcFile := filepath.Join(rootDir, catalog) + _, err := os.Stat(fbcFile) + Expect(err).To(HaveOccurred()) + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + It("should report content does not exist", func() { + Expect(store.ContentExists(catalog)).To(BeFalse()) + }) + }) + }) +}) + +var _ = Describe("LocalDir Server Handler tests", func() { + var ( + testServer *httptest.Server + store LocalDirV1 + ) + BeforeEach(func() { + d, err := os.MkdirTemp(GinkgoT().TempDir(), "cache") + Expect(err).ToNot(HaveOccurred()) + Expect(os.MkdirAll(filepath.Join(d, "test-catalog", v1ApiPath), 0700)).To(Succeed()) + store = LocalDirV1{RootDir: d, RootURL: &url.URL{Path: urlPrefix}} + testServer = httptest.NewServer(store.StorageServerHandler()) + + }) + It("gets 404 for the path /", func() { + expectNotFound(testServer.URL) + }) + It("gets 404 for the path /catalogs/", func() { + expectNotFound(fmt.Sprintf("%s/%s", testServer.URL, "/catalogs/")) + }) + It("gets 404 for the path /catalogs/test-catalog/", func() { + expectNotFound(fmt.Sprintf("%s/%s", testServer.URL, "/catalogs/test-catalog/")) + }) + It("gets 404 for the path /test-catalog/foo.txt", func() { + // This ensures that even if the file exists, the URL must contain the /catalogs/ prefix + Expect(os.WriteFile(filepath.Join(store.RootDir, "test-catalog", "foo.txt"), []byte("bar"), 0600)).To(Succeed()) + expectNotFound(fmt.Sprintf("%s/%s", testServer.URL, "/test-catalog/foo.txt")) + }) + It("gets 404 for the path /catalogs/test-catalog/non-existent.txt", func() { + expectNotFound(fmt.Sprintf("%s/%s", testServer.URL, "/catalogs/test-catalog/non-existent.txt")) + }) + It("gets 200 for the path /catalogs/foo.txt", func() { + expectedContent := []byte("bar") + Expect(os.WriteFile(filepath.Join(store.RootDir, "foo.txt"), expectedContent, 0600)).To(Succeed()) + expectFound(fmt.Sprintf("%s/%s", testServer.URL, "/catalogs/foo.txt"), expectedContent) + }) + It("gets 200 for the path /catalogs/test-catalog/foo.txt", func() { + expectedContent := []byte("bar") + Expect(os.WriteFile(filepath.Join(store.RootDir, "test-catalog", "foo.txt"), expectedContent, 0600)).To(Succeed()) + expectFound(fmt.Sprintf("%s/%s", testServer.URL, "/catalogs/test-catalog/foo.txt"), expectedContent) + }) + It("ignores accept-encoding for the path /catalogs/test-catalog/api/v1/all with size < 1400 bytes", func() { + expectedContent := []byte("bar") + Expect(os.WriteFile(filepath.Join(store.RootDir, "test-catalog", v1ApiPath, v1ApiData), expectedContent, 0600)).To(Succeed()) + expectFound(fmt.Sprintf("%s/%s", testServer.URL, "/catalogs/test-catalog/api/v1/all"), expectedContent) + }) + It("provides gzipped content for the path /catalogs/test-catalog/api/v1/all with size > 1400 bytes", func() { + expectedContent := []byte(testCompressableJSON) + Expect(os.WriteFile(filepath.Join(store.RootDir, "test-catalog", v1ApiPath, v1ApiData), expectedContent, 0600)).To(Succeed()) + expectFound(fmt.Sprintf("%s/%s", testServer.URL, "/catalogs/test-catalog/api/v1/all"), expectedContent) + }) + It("provides json-lines format for the served JSON catalog", func() { + catalog := "test-catalog" + unpackResultFS := &fstest.MapFS{ + "catalog.json": &fstest.MapFile{Data: []byte(testCompressableJSON), Mode: os.ModePerm}, + } + err := store.Store(context.Background(), catalog, unpackResultFS) + Expect(err).To(Not(HaveOccurred())) + + expectedContent, err := generateJSONLines([]byte(testCompressableJSON)) + Expect(err).To(Not(HaveOccurred())) + path, err := url.JoinPath(testServer.URL, urlPrefix, catalog, v1ApiPath, v1ApiData) + Expect(err).To(Not(HaveOccurred())) + expectFound(path, []byte(expectedContent)) + }) + It("provides json-lines format for the served YAML catalog", func() { + catalog := "test-catalog" + yamlData, err := makeYAMLFromConcatenatedJSON([]byte(testCompressableJSON)) + Expect(err).To(Not(HaveOccurred())) + unpackResultFS := &fstest.MapFS{ + "catalog.yaml": &fstest.MapFile{Data: yamlData, Mode: os.ModePerm}, + } + err = store.Store(context.Background(), catalog, unpackResultFS) + Expect(err).To(Not(HaveOccurred())) + + expectedContent, err := generateJSONLines(yamlData) + Expect(err).To(Not(HaveOccurred())) + path, err := url.JoinPath(testServer.URL, urlPrefix, catalog, v1ApiPath, v1ApiData) + Expect(err).To(Not(HaveOccurred())) + expectFound(path, []byte(expectedContent)) + }) + AfterEach(func() { + testServer.Close() + }) +}) + +func expectNotFound(url string) { + resp, err := http.Get(url) //nolint:gosec + Expect(err).To(Not(HaveOccurred())) + Expect(resp.StatusCode).To(Equal(http.StatusNotFound)) + Expect(resp.Body.Close()).To(Succeed()) +} + +func expectFound(url string, expectedContent []byte) { + req, err := http.NewRequest(http.MethodGet, url, nil) + Expect(err).To(Not(HaveOccurred())) + req.Header.Set("Accept-Encoding", "gzip") + resp, err := http.DefaultClient.Do(req) + Expect(err).To(Not(HaveOccurred())) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + + var actualContent []byte + switch resp.Header.Get("Content-Encoding") { + case "gzip": + Expect(len(expectedContent)).To(BeNumerically(">", 1400), + fmt.Sprintf("gzipped content should only be provided for content larger than 1400 bytes, but our expected content is only %d bytes", len(expectedContent))) + gz, err := gzip.NewReader(resp.Body) + Expect(err).To(Not(HaveOccurred())) + actualContent, err = io.ReadAll(gz) + Expect(err).To(Not(HaveOccurred())) + default: + actualContent, err = io.ReadAll(resp.Body) + Expect(len(expectedContent)).To(BeNumerically("<", 1400), + fmt.Sprintf("plaintext content should only be provided for content smaller than 1400 bytes, but we received plaintext for %d bytes\n expectedContent:\n%s\n", len(expectedContent), expectedContent)) + Expect(err).To(Not(HaveOccurred())) + } + + Expect(actualContent).To(Equal(expectedContent)) + Expect(resp.Body.Close()).To(Succeed()) +} + +const testBundleTemplate = `--- +image: %s +name: %s +schema: olm.bundle +package: %s +relatedImages: + - name: %s + image: %s +properties: + - type: olm.bundle.object + value: + data: %s + - type: some.other + value: + data: arbitrary-info +` + +const testPackageTemplate = `--- +defaultChannel: %s +name: %s +schema: olm.package +` + +const testChannelTemplate = `--- +schema: olm.channel +package: %s +name: %s +entries: + - name: %s +` + +// by default the compressor will only trigger for files larger than 1400 bytes +const testCompressableJSON = `{ + "defaultChannel": "stable-v6.x", + "name": "cockroachdb", + "schema": "olm.package" +} +{ + "entries": [ + { + "name": "cockroachdb.v5.0.3" + }, + { + "name": "cockroachdb.v5.0.4", + "replaces": "cockroachdb.v5.0.3" + } + ], + "name": "stable-5.x", + "package": "cockroachdb", + "schema": "olm.channel" +} +{ + "entries": [ + { + "name": "cockroachdb.v6.0.0", + "skipRange": "<6.0.0" + } + ], + "name": "stable-v6.x", + "package": "cockroachdb", + "schema": "olm.channel" +} +{ + "image": "quay.io/openshift-community-operators/cockroachdb@sha256:a5d4f4467250074216eb1ba1c36e06a3ab797d81c431427fc2aca97ecaf4e9d8", + "name": "cockroachdb.v5.0.3", + "package": "cockroachdb", + "properties": [ + { + "type": "olm.gvk", + "value": { + "group": "charts.operatorhub.io", + "kind": "Cockroachdb", + "version": "v1alpha1" + } + }, + { + "type": "olm.package", + "value": { + "packageName": "cockroachdb", + "version": "5.0.3" + } + } + ], + "relatedImages": [ + { + "name": "", + "image": "quay.io/helmoperators/cockroachdb:v5.0.3" + }, + { + "name": "", + "image": "quay.io/openshift-community-operators/cockroachdb@sha256:a5d4f4467250074216eb1ba1c36e06a3ab797d81c431427fc2aca97ecaf4e9d8" + } + ], + "schema": "olm.bundle" +} +{ + "image": "quay.io/openshift-community-operators/cockroachdb@sha256:f42337e7b85a46d83c94694638e2312e10ca16a03542399a65ba783c94a32b63", + "name": "cockroachdb.v5.0.4", + "package": "cockroachdb", + "properties": [ + { + "type": "olm.gvk", + "value": { + "group": "charts.operatorhub.io", + "kind": "Cockroachdb", + "version": "v1alpha1" + } + }, + { + "type": "olm.package", + "value": { + "packageName": "cockroachdb", + "version": "5.0.4" + } + } + ], + "relatedImages": [ + { + "name": "", + "image": "quay.io/helmoperators/cockroachdb:v5.0.4" + }, + { + "name": "", + "image": "quay.io/openshift-community-operators/cockroachdb@sha256:f42337e7b85a46d83c94694638e2312e10ca16a03542399a65ba783c94a32b63" + } + ], + "schema": "olm.bundle" +} +{ + "image": "quay.io/openshift-community-operators/cockroachdb@sha256:d3016b1507515fc7712f9c47fd9082baf9ccb070aaab58ed0ef6e5abdedde8ba", + "name": "cockroachdb.v6.0.0", + "package": "cockroachdb", + "properties": [ + { + "type": "olm.gvk", + "value": { + "group": "charts.operatorhub.io", + "kind": "Cockroachdb", + "version": "v1alpha1" + } + }, + { + "type": "olm.package", + "value": { + "packageName": "cockroachdb", + "version": "6.0.0" + } + } + ], + "relatedImages": [ + { + "name": "", + "image": "quay.io/cockroachdb/cockroach-helm-operator:6.0.0" + }, + { + "name": "", + "image": "quay.io/openshift-community-operators/cockroachdb@sha256:d3016b1507515fc7712f9c47fd9082baf9ccb070aaab58ed0ef6e5abdedde8ba" + } + ], + "schema": "olm.bundle" +} +` + +// makeYAMLFromConcatenatedJSON takes a byte slice of concatenated JSON objects and returns a byte slice of concatenated YAML objects. +func makeYAMLFromConcatenatedJSON(data []byte) ([]byte, error) { + var msg json.RawMessage + var delimiter = []byte("---\n") + var yamlData []byte + + yamlData = append(yamlData, delimiter...) + + dec := json.NewDecoder(bytes.NewReader(data)) + for { + err := dec.Decode(&msg) + if errors.Is(err, io.EOF) { + break + } + y, err := yaml.JSONToYAML(msg) + if err != nil { + return []byte{}, err + } + yamlData = append(yamlData, delimiter...) + yamlData = append(yamlData, y...) + } + return yamlData, nil +} + +// generateJSONLines takes a byte slice of concatenated JSON objects and returns a JSONlines-formatted string. +func generateJSONLines(in []byte) (string, error) { + var out strings.Builder + reader := bytes.NewReader(in) + + err := declcfg.WalkMetasReader(reader, func(meta *declcfg.Meta, err error) error { + if err != nil { + return err + } + + if meta != nil && meta.Blob != nil { + if meta.Blob[len(meta.Blob)-1] != '\n' { + return fmt.Errorf("blob does not end with newline") + } + } + + _, err = out.Write(meta.Blob) + if err != nil { + return err + } + return nil + }) + return out.String(), err +} diff --git a/catalogd/internal/storage/storage.go b/catalogd/internal/storage/storage.go new file mode 100644 index 000000000..458ff040b --- /dev/null +++ b/catalogd/internal/storage/storage.go @@ -0,0 +1,19 @@ +package storage + +import ( + "context" + "io/fs" + "net/http" +) + +// Instance is a storage instance that stores FBC content of catalogs +// added to a cluster. It can be used to Store or Delete FBC in the +// host's filesystem. It also a manager runnable object, that starts +// a server to serve the content stored. +type Instance interface { + Store(ctx context.Context, catalog string, fsys fs.FS) error + Delete(catalog string) error + BaseURL(catalog string) string + StorageServerHandler() http.Handler + ContentExists(catalog string) bool +} diff --git a/catalogd/internal/storage/suite_test.go b/catalogd/internal/storage/suite_test.go new file mode 100644 index 000000000..b0c512de7 --- /dev/null +++ b/catalogd/internal/storage/suite_test.go @@ -0,0 +1,29 @@ +/* +Copyright 2023. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package storage + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Storage Suite") +} diff --git a/catalogd/internal/third_party/server/server.go b/catalogd/internal/third_party/server/server.go new file mode 100644 index 000000000..cfdec7b3b --- /dev/null +++ b/catalogd/internal/third_party/server/server.go @@ -0,0 +1,123 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// this is copied from https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/77b08a845e451b695cfa25b79ebe277d85064345/pkg/manager/server.go +// we will remove this once we update to a version of controller-runitme that has this included +// https://github.com/kubernetes-sigs/controller-runtime/pull/2473 + +package server + +import ( + "context" + "errors" + "net" + "net/http" + "time" + + "github.com/go-logr/logr" + + crlog "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +var ( + _ manager.Runnable = (*Server)(nil) + _ manager.LeaderElectionRunnable = (*Server)(nil) +) + +// Server is a general purpose HTTP(S) server Runnable for a manager. +// It is used to serve some internal handlers for health probes and profiling, +// but it can also be used to run custom servers. +type Server struct { + // Kind is an optional string that describes the purpose of the server. It is used in logs to distinguish + // among multiple servers. + Kind string + + // Log is the logger used by the server. If not set, a logger will be derived from the context passed to Start. + Log logr.Logger + + // Server is the HTTP server to run. It is required. + Server *http.Server + + // Listener is an optional listener to use. If not set, the server start a listener using the server.Addr. + // Using a listener is useful when the port reservation needs to happen in advance of this runnable starting. + Listener net.Listener + + // OnlyServeWhenLeader is an optional bool that indicates that the server should only be started when the manager is the leader. + OnlyServeWhenLeader bool + + // ShutdownTimeout is an optional duration that indicates how long to wait for the server to shutdown gracefully. If not set, + // the server will wait indefinitely for all connections to close. + ShutdownTimeout *time.Duration +} + +// Start starts the server. It will block until the server is stopped or an error occurs. +func (s *Server) Start(ctx context.Context) error { + log := s.Log + if log.GetSink() == nil { + log = crlog.FromContext(ctx) + } + if s.Kind != "" { + log = log.WithValues("kind", s.Kind) + } + log = log.WithValues("addr", s.addr()) + + serverShutdown := make(chan struct{}) + go func() { + <-ctx.Done() + log.Info("shutting down server") + + shutdownCtx := context.Background() + if s.ShutdownTimeout != nil { + var shutdownCancel context.CancelFunc + shutdownCtx, shutdownCancel = context.WithTimeout(context.Background(), *s.ShutdownTimeout) + defer shutdownCancel() + } + + if err := s.Server.Shutdown(shutdownCtx); err != nil { + log.Error(err, "error shutting down server") + } + close(serverShutdown) + }() + + log.Info("starting server") + if err := s.serve(); err != nil && !errors.Is(err, http.ErrServerClosed) { + return err + } + + <-serverShutdown + return nil +} + +// NeedLeaderElection returns true if the server should only be started when the manager is the leader. +func (s *Server) NeedLeaderElection() bool { + return s.OnlyServeWhenLeader +} + +func (s *Server) addr() string { + if s.Listener != nil { + return s.Listener.Addr().String() + } + return s.Server.Addr +} + +func (s *Server) serve() error { + if s.Listener != nil { + return s.Server.Serve(s.Listener) + } + + return s.Server.ListenAndServe() +} diff --git a/catalogd/internal/version/version.go b/catalogd/internal/version/version.go new file mode 100644 index 000000000..73ba429a9 --- /dev/null +++ b/catalogd/internal/version/version.go @@ -0,0 +1,36 @@ +package version + +import ( + "fmt" + "runtime" + "strings" + + "github.com/blang/semver/v4" + genericversion "k8s.io/apimachinery/pkg/version" +) + +var ( + gitVersion = "unknown" + gitCommit = "unknown" // sha1 from git, output of $(git rev-parse HEAD) + gitTreeState = "unknown" // state of git tree, either "clean" or "dirty" + commitDate = "unknown" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') +) + +// Version returns a version struct for the build +func Version() genericversion.Info { + info := genericversion.Info{ + GitVersion: gitVersion, + GitCommit: gitCommit, + GitTreeState: gitTreeState, + BuildDate: commitDate, + GoVersion: runtime.Version(), + Compiler: runtime.Compiler, + Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), + } + v, err := semver.Parse(strings.TrimPrefix(gitVersion, "v")) + if err == nil { + info.Major = fmt.Sprintf("%d", v.Major) + info.Minor = fmt.Sprintf("%d", v.Minor) + } + return info +} diff --git a/catalogd/internal/webhook/cluster_catalog_webhook.go b/catalogd/internal/webhook/cluster_catalog_webhook.go new file mode 100644 index 000000000..3938939a7 --- /dev/null +++ b/catalogd/internal/webhook/cluster_catalog_webhook.go @@ -0,0 +1,46 @@ +package webhook + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" +) + +// +kubebuilder:webhook:admissionReviewVersions={v1},failurePolicy=Fail,groups=olm.operatorframework.io,mutating=true,name=inject-metadata-name.olm.operatorframework.io,path=/mutate-olm-operatorframework-io-v1-clustercatalog,resources=clustercatalogs,verbs=create;update,versions=v1,sideEffects=None,timeoutSeconds=10 + +// +kubebuilder:rbac:groups=olm.operatorframework.io,resources=clustercatalogs,verbs=get;list;watch;patch;update + +// ClusterCatalog wraps the external v1.ClusterCatalog type and implements admission.Defaulter +type ClusterCatalog struct{} + +// Default is the method that will be called by the webhook to apply defaults. +func (r *ClusterCatalog) Default(ctx context.Context, obj runtime.Object) error { + log := log.FromContext(ctx) + log.Info("Invoking Default method for ClusterCatalog", "object", obj) + catalog, ok := obj.(*catalogdv1.ClusterCatalog) + if !ok { + return fmt.Errorf("expected a ClusterCatalog but got a %T", obj) + } + + // Defaulting logic: add the "olm.operatorframework.io/metadata.name" label + if catalog.Labels == nil { + catalog.Labels = map[string]string{} + } + catalog.Labels[catalogdv1.MetadataNameLabel] = catalog.GetName() + log.Info("default", catalogdv1.MetadataNameLabel, catalog.Name, "labels", catalog.Labels) + + return nil +} + +// SetupWebhookWithManager sets up the webhook with the manager +func (r *ClusterCatalog) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&catalogdv1.ClusterCatalog{}). + WithDefaulter(r). + Complete() +} diff --git a/catalogd/internal/webhook/cluster_catalog_webhook_test.go b/catalogd/internal/webhook/cluster_catalog_webhook_test.go new file mode 100644 index 000000000..33d07a833 --- /dev/null +++ b/catalogd/internal/webhook/cluster_catalog_webhook_test.go @@ -0,0 +1,106 @@ +package webhook + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" +) + +// Define a dummy struct that implements runtime.Object but isn't a ClusterCatalog +type NotClusterCatalog struct { + metav1.TypeMeta + metav1.ObjectMeta +} + +func (n *NotClusterCatalog) DeepCopyObject() runtime.Object { + return &NotClusterCatalog{} +} + +func TestClusterCatalogDefaulting(t *testing.T) { + tests := map[string]struct { + clusterCatalog runtime.Object + expectedLabels map[string]string + expectError bool + errorMessage string + }{ + "no labels provided, name label added": { + clusterCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + }, + }, + expectedLabels: map[string]string{ + "olm.operatorframework.io/metadata.name": "test-catalog", + }, + expectError: false, + }, + "labels already present, name label added": { + clusterCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Labels: map[string]string{ + "existing": "label", + }, + }, + }, + expectedLabels: map[string]string{ + "olm.operatorframework.io/metadata.name": "test-catalog", + "existing": "label", + }, + expectError: false, + }, + "name label already present, no changes": { + clusterCatalog: &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-catalog", + Labels: map[string]string{ + "olm.operatorframework.io/metadata.name": "existing-name", + }, + }, + }, + expectedLabels: map[string]string{ + "olm.operatorframework.io/metadata.name": "test-catalog", // Defaulting should still override this to match the object name + }, + expectError: false, + }, + "invalid object type, expect error": { + clusterCatalog: &NotClusterCatalog{ + TypeMeta: metav1.TypeMeta{ + Kind: "NotClusterCatalog", + APIVersion: "v1", + }, + }, + expectedLabels: nil, + expectError: true, + errorMessage: "expected a ClusterCatalog but got a *webhook.NotClusterCatalog", + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + // Arrange + clusterCatalogWrapper := &ClusterCatalog{} + + // Act + err := clusterCatalogWrapper.Default(context.TODO(), tc.clusterCatalog) + + // Assert + if tc.expectError { + require.Error(t, err) + assert.Contains(t, err.Error(), tc.errorMessage) + } else { + assert.NoError(t, err) + if tc.expectedLabels != nil { + labels := tc.clusterCatalog.(*catalogdv1.ClusterCatalog).Labels + assert.Equal(t, tc.expectedLabels, labels) + } + } + }) + } +} diff --git a/catalogd/pprof/README.md b/catalogd/pprof/README.md new file mode 100644 index 000000000..e782ac60f --- /dev/null +++ b/catalogd/pprof/README.md @@ -0,0 +1,195 @@ +## pprof + +> **Warning** +> This pprof data is based on early versions of catalogd and has not been updated since. The data is likely not accurate anymore. +> A decision about removing or updating this data will be made in the future. + +This folder contains some profiles that can be read using [pprof](https://github.com/google/pprof) to show how the core kubernetes apiserver and the custom catalogd apiserver CPU & Memory utilization is affected by the creation and reconciliation of the sample `Catalog` CR found at `../config/samples/core_v1_clustercatalog.yaml`. + +Instead of providing static screenshots and losing the interactivity associated with these `pprof` profiles, each of the files with the extension `.pb` can be used to view the profiles that were the result of running `pprof` against the live processes. + +To view the `pprof` profiles in the most interactive way (or if you have no prior `pprof`experience) it is recommended to run: +``` +go tool pprof -http=localhost: somefile.pb +``` + +This will start up an interactive web UI for viewing the profile data for a specific file on `localhost:`. There are quite a few different ways this data can be viewed so feel free to play around and find the view which gives you the most meaningful information. + +If you know your way around `pprof` you *should* be able to run any other variations of `pprof` with these files as well. + +Here is a brief breakdown of what information is provided in each profile file in this directory: +- `kubeapiserver_cpu_profile.pb` - This is the CPU utilization of the core kube-apiserver +- `kubeapiserver_heap_profile.pb` - This is the Memory utilization of the core kube-apiserver +- `catalogd_apiserver_cpu_profile.pb` - This is the CPU utilization of the custom catalogd apiserver +- `catalogd_apiserver_heap_profile.pb` - This is the Memory utilization of the custom catalogd apiserver +- `manager_cpu_profile.pb` - This is the CPU utilization of the Catalog controller (and other controllers associated with this manager). +- `manager_heap_profile.pb` - This is the Memory utilization of the Catalog controller (and other controllers associated with this manager). +- `kubeapiserver_alone_cpu_profile.pb` - This is the CPU utilization for the core kube-apiserver without running our custom apiserver +- `kubeapiserver_alone_heap_profile.pb` - This is the Memory utilization for the core kube-apiserver without running our custom apiserver + +> **NOTE**: All profiles were collected ASAP after all child resources were created from the reconciliation of the sample `Catalog` CR. + + +## Pprof Breakdown +In this section, we will break down the differences between how the core kube-apiserver resource utilization was impacted when running with and without the custom catalogd apiserver in an effort to determine how beneficial it is to use a custom apiserver. + +> **NOTE**: All this information was compared by someone who is not very experienced with using `pprof`. If you find that any of these values are incorrect or the calculations don't seem to make sense, feel free to create an issue or open a PR to update these findings. + +### CPU Utilization + +| Metric | kube-apiserver alone | kube-apiserver w\custom | Normalized Difference | +| ------- | -------------------- | ----------------------- | --------------------- | +| cpu | 1.72s / 30s (5.73%) | 1.99s / 30.06s (6.62%) | 1720ms / 60.06s (2.86%) | + +The `Normalized Difference` Metric was evaluated by running: +``` +go tool pprof -http=localhost:6060 -diff_base=pprof/kubeapiserver_alone_cpu_profile.pb -normalize pprof/kubeapiserver_cpu_profile.pb +``` +This command will normalize the profiles to better compare the differences. In its simplest form this difference was calculated by `pprof/kubeapiserver_alone_cpu_profile.pb - pprof/kubeapiserver_cpu_profile.pb` + +According to the `Normalized Difference`, there appears to be little to no difference in the amount of time the CPU is utilized (almost 0). + +### Memory Utilization + +| Metric | kube-apiserver alone | kube-apiserver w\custom | Normalized Difference | +| ------------- | -------------------- | ----------------------- | --------------------- | +| inuse_space | 126.85MB | 139.67MB | -0.02kB, 1.7e-05% of 129891.07kB total | +| inuse_objects | 721278 | 640819 | -9, 0.0012% of 721278 total | +| alloc_space | 1924.76MB | 3455.75MB | 0, 2e-07% of 1970951.57kB total | +| alloc_objects | 19717785 | 33134306 | 102, 0.00052% of 19717785 total | + +The `Normalized Difference` Metric was evaluated by running: +``` +go tool pprof -http=localhost:6060 -diff_base=pprof/kubeapiserver_alone_heap_profile.pb -normalize pprof/kubeapiserver_heap_profile.pb +``` +This command will normalize the profiles to better compare the differences. In its simplest form this difference was calculated by `pprof/kubeapiserver_alone_heap_profile.pb - pprof/kubeapiserver_heap_profile.pb` + +According to the `Normalized Difference`, there appears to be: +- An additional 0.02kB space used when in combination with the custom catalogd apiserver +- An additional 9 objects used when in combination with the custom catalogd apiserver +- No additional space allocated when in combination with the custom catalogd apiserver +- 102 less objects allocated when in combination with the custom catalogd apiserver + + +## Metric Server Analysis +This section will be an analysis of the on cluster CPU/Memory consumption of the pods corresponding to the core kube-apiserver, catalogd apiserver and the controller-manager. + +This section is being added as the pprof metrics don't necessarily show the whole picture. This section will include 2 scenarios for the core kube-apiserver: +1. The CPU/Memory consumption of the kube-apiserver pod without the catalogd apisver running +2. The CPU/Memory consumption of the kube-apiserver pod with the catalogd apisever running + +### Core kube-apiserver without catalogd apiserver +![kube-apiserver CPU and Memory metrics graphs without custom apiserver](images/kubeapiserver_alone_metrics.png) + +**TLDR**: CPU utilization spike of 0.156 cores and settles ~0.011 cores above prior utilization. Memory consumption increase of 22Mi. + +This image shows the spike in CPU utilization and the increase in Memory consumption. In this scenario, the command: +``` +kubectl apply -f config/samples/core_v1_clustercatalog.yaml +``` +was run right at 1:44 PM. + +The CPU spike lasted ~3 minutes and the values were: +- 1:44PM - 0.067 cores +- 1:45PM (PEAK) - 0.223 cores +- 1:47PM - 0.078 cores + +With this, we can see that without the catalogd apiserver the core kube-apiserver had a CPU utilization spike of 0.156 cores and then settled at ~0.011 cores above what the utilization was prior to the reconciliation of the sample `Catalog` CR. + +The memory consumption increased over the span of ~3 minutes and then stabilized. The values were: +- 1:44PM - 289Mi +- 1:45PM - 305Mi +- 1:47PM - 311Mi + +With this, we can see that without the catalogd apiserver the core kube-apiserver had a memory consumption increase of 22Mi. + +### Core kube-apiserver with catalogd apiserver + +#### kube-apiserver: +![kube-apiserver CPU and mem metric graph with custom apiserver](images/kubeapiserver_metrics.png) + +**TLDR**: CPU utilization spike of 0.125 cores and settles ~0.001 cores above prior utilization. Memory consumption increase of ~26Mi. + +This image shows the spike in CPU utilization and the increase in Memory consumption. In this scenario, the command: +``` +kubectl apply -f config/samples/core_v1_clustercatalog.yaml +``` +was run right at 3:06 PM + +The CPU spike lasted ~3 minutes and the values were: +- 3:06PM - 0.09 cores +- 3:07PM - 0.109 cores +- 3:08 PM (PEAK) - 0.215 cores +- 3:09 PM - 0.091 cores + +With this, we can see that with the catalogd apiserver the core kube-apiserver had a CPU utilization spike of 0.125 cores and then settled at ~0.001 cores above what the utilization was prior to the reconciliation of the sample `Catalog` CR. + +The memory consumption increased over the span of ~3 minutes and then stabilized. The values were: +- 3:06PM - 337Mi +- 3:07PM - 361Mi +- 3:08 PM - 363Mi +- 3:09 PM - 363Mi + +With this, we can see that with the catalogd apiserver the core kube-apiserver had a memory consumption increase of ~26Mi. + +#### catalogd apiserver +![catalogd custom apiserver CPU and memory consumption graphs](images/customapiserver_metrics.png) + +**TLDR**: potential increase of ~0.012 cores, but more likely ~0.002 cores. Memory consumption increase of ~0.1Mi + +This image shows the spike in CPU utilization and the increase in Memory consumption. In this scenario, the command: +``` +kubectl apply -f config/samples/core_v1_clustercatalog.yaml +``` +was run right at 3:06 PM + +The CPU consumption increase lasted ~3 minutes and the values were: +- 3:06PM - 0.002 cores (there was a weird dip right here from ~0.012 cores at 3:05PM) +- 3:07PM - 0.01 cores +- 3:08 PM - 0.012 cores +- 3:09 PM - 0.014 cores + +We can see that our custom apiserver had a CPU utilization increase of ~0.012 cores. If we take into consideration the weird dip and place the starting value at ~0.12 cores the CPU utilization increase is only ~0.002 cores. + +The memory consumption increased over the span of ~3 minutes. The values were: +- 3:06PM - 77.9Mi +- 3:07PM - 77.9Mi +- 3:08 PM - 77.9Mi +- 3:09 PM - 78Mi (stable around this after) + +We can see that our custom apiserver had a memory consumption increase of ~0.1Mi. + +#### Summary +Comparing the results of the kube-apiserver running both with and without the catalogd apiserver, we can see that: +- The kube-apiserver CPU utilization spikes 0.031 cores less and settles ~0.01 cores less when running in combination with the catalogd apiserver +- The kube-apiserver consumes ~4Mi more memory when running in combination with the catalogd apiserver + + +Overall, when running both the kube-apiserver and the catalogd apiserver the total CPU utilization remains roughly the same while the overall memory consumption increases ~73Mi. + +### controller-manager metrics +![controller-manager CPU & memory metric graphs](images/controller_metrics.png) + +**TLDR**: CPU spike of 0.288 cores, settling ~0.003 cores above the previous consumption. Memory consumption of ~232.2Mi. + +This image shows the spike in CPU utilization and the increase in Memory consumption. In this scenario, the command: +``` +kubectl apply -f config/samples/core_v1_clustercatalog.yaml +``` +was run right at 3:06 PM + +The CPU spike lasted ~3 minutes and the values were: +- 3:06PM - 0.001 cores +- 3:07PM (PEAK) - 0.289 cores +- 3:08PM - 0.177 cores +- 3:09PM - 0.004 cores + +We can see that the controller manager had a CPU utilization spike of 0.288 cores and then settled ~0.003 cores above the previous consumption. This is likely due to the large number of creation requests that needed to be made (~170 `Package` CR and ~1301 `BundleMetadata` CR creation requests). + +The memory consumption increased over the span of ~3 minutes. The values were: +- 3:06PM - 49.8Mi +- 3:07PM - 248Mi +- 3:08PM - 282Mi +- 3:09PM - 282Mi + +We can see that our controller-manager had a memory consumption increase of ~232.2Mi. This is likely due to the fact that the cache was populated with ~170 `Package` CRs and ~1301 `BundleMetadata` CRs. diff --git a/catalogd/pprof/catalogd_apiserver_cpu_profile.pb b/catalogd/pprof/catalogd_apiserver_cpu_profile.pb new file mode 100644 index 0000000000000000000000000000000000000000..8ffee8b51247d622cddb1022c211de383a879fa0 GIT binary patch literal 8115 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 YUDf&cuV4ACwNL(ken0<*eEf6&2jY$v$^ZZW literal 0 HcmV?d00001 diff --git a/catalogd/pprof/catalogd_apiserver_heap_profile.pb b/catalogd/pprof/catalogd_apiserver_heap_profile.pb new file mode 100644 index 0000000000000000000000000000000000000000..3b422419d645f4e5810c17e610e58df28a03250c GIT binary patch literal 25762 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 N;W<|{HmcE|{XZnFDK!89 literal 0 HcmV?d00001 diff --git a/catalogd/pprof/images/controller_metrics.png b/catalogd/pprof/images/controller_metrics.png new file mode 100644 index 0000000000000000000000000000000000000000..4d842fdbc0a263d06abab27765adfa35497543d9 GIT binary patch literal 116782 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%0D%C6f#7*ZP;|q}yQ18+(GdLm6P@x8iI0 z9Wda@0E*0}XWp#u!=|?d0IXCCDWy!5_ua`-QTP=pjEqbQ5Gh)n>1&z+ z$b%8727Rl(ty|9#;BUQBqGPZ`-ZNQ3HfGNBXdV`eNm|n4Qpc1}>Dq}KJ8p+)#nYVV zpq{W4cIehWXHt6k;fC%zaa!A63Zyf%Jb&n5czS{SGIxS`PUr~5D+PhnYQQ;PO*L|Q znI+31-t}-7P?+|AIjtYD8M@MwshW14H%jm99!Jwppp?l=^lR*jhD<)Mi<(tcZLi(W zDsEi*74YseuWuS3V`_o3E=j{ocJh7%G15OYc09Nyh1KmjS|nm(Z~F%e1z|w2tn`Ts zW)x_iy_`G#WA9t_Y(#kD4qZnkp!>$mnK>8+Km^`H(y_b=(m)Q|^)g(taYrRw_|q;s zv&GbcR&RP);IG1J=eZF(RvhahMe5}mXbWD4LArM!)TkyZ+(`n1-)0^je2lOIps7^+j|LqEEr%&v55f%y^2R(Q zl^XQ(u1?l@awl-xmaf+~@xn482YM>5eP%pgb6>e($ zoFFY+#i(xs zSAb241+_+Fcb3+jB!wa^Rb%80vnb99tg#$E zex>V_!!jtI#N?j7p5JdUE)|c7vnfIca5fpLgwv5?O*#WXW;i<7l|5t44nnJ>10q5F zuoZF6Kc;EnaKT;0)n4L@yC7yT;=G!~5A8Q-77~r~c49)GrrjJ{m-$mK7nvOb9=2*z z<*y2ez|wPZUH<4czW;+80Qoj({eNWWLFq{%xt~8qbQnk_n2sd%1%ulU$_mJ`v*?!{ z5Y(ozy^ql_XOnI*a8Qa6K#+W?nqg#ZhO50Ur)pK>=7algj&kf&pk*30vW&UQY zt`~=(%0v-WX6j!KrmB6Gl+QeXGQ?KIC?na)YT$cb9M@4I=b;52XNOHOoG>ADgY2mk zQhH29+NdnQ=-nOYb_>tZu3OsjuA!9pA^`g!Rd(iQh^G)0hG-U1mNkJyu!#-V)6?f3 z-umOpZrc#a-}DbpK_e^Zhsvn&@H4yf8Z!FtVju?yS~IML+}zO6g zA)yl$KIydy0Se&JqrVY-YF2Jz(;G;wV(&m_Ac~8IV@AnR-nP~?$oxGQP5%$iAq<~< z#q98mwK=*jq|xORIb0!$u>YKV0ektUbe_Wn0>jrJ$SOXXY+^Esx-YfPT_IwlP#+2M z)b)-Z&XC!{cdEt>?_X$gb0JJBD}8Z3H4#T06TO>n9^Iau&5OXoRx12F&vLd(2nVnt zkfM8F9Zv+=o%)$m?;Cdx%_z5>g+morOdt$xI)ToDJX|0nDXcyS$@3$W$?M+<{;NAH zd%L6UNzKZXfC(v+ zP)Ht$kL)Y6iTf>Hz`6`OYsE==mTlI*WcK;B`n~wh=6e3{+S&a(hDiOd8X|!4j#%Ex z(vKupKkfjZu&qetdmm~+i@o-6=F20Hcq_)7_LyjJ4*ZZH?8(eq+UFcO1?Yq5EH)yiU$gF z_i(4M)nTL+h}kq>US#K^s1W1phRV_qHAq-H>nr1^;P?;&fel$umBxN<6`=A)-sU}K z9Hxwle#AiuS<0Tr*H+>~+CVgw(|3EJKHeU6GwB^GuJpEzrJO6d7$NFhK{zGe=DF*2 z6>-=#Rjdl?JNaG?+8OaA_s>U;NO@H}z7Fi!B8-zXl=}7UQXDWld7;#Jw`=yflSf1> zaGIJic9$l2sHzo1Q-v2>(qjxW{Pu=yPU7mym|G(ed(?KHhe+# zV#t{#8fzxbUS^QATHgbv&7Wu4i-xKtN{$q)q zZc1V)dC~|st0dM$DCjrcM%%$K^UeG_3~3ppOAxbrSn}q)(iTW;s09xT={{@e<)X%C zR!lrpnjlaM7TSRztO(lmytQAd`@tcDRV;S^sU6f{{6mPpQ??-wuN3`Tp#v4(-hMEE zZ6$1a_#(E=VSB9MoGcH8n)I*H188!MK9DYI?(kXs(7)1apwReIpP*ObD57Ax&5jcQ zdFHLN6J}hLcuo#V5ZzS|odn%)tuZK&M4S9E8V1L~#o7AD!^1}Knt>>M69+2mJOJ|7 zHy@v5#fhGR>sI1KKOg{)!Ok1sW5|KqwI3uPry5H~AWz-^Z0KuREH5iA&pbqu#R7yR z8Gn>;%=DbL?&f|$;BN!KDF9*r(_tEV63k+&_Db)O-;Uy2c(DE@U(_5AMDEQBQag;5T6LZf~Rl61A3b74P=bF3h3N-K-TpE-zy-WfsnZ&RH3BmRQ;nM zu+czjG(x06&P4YBVhLX@perW?!2Z)Rh0z;*XdQQkwS%3ZFDiyea{X{hwBr{QVOGkz7~H*#D+Vn|F!DI72Rji-r7(I8ca-N_bT9Yy%!uft_Hc+d+MS&tN2D(G<2y7AFYQyGNyx06 zq)oeK==EK04Mw?|mp7uaj9~Q7Y5SqG9~{PB1}}nKXV7lz5#q)Ei}+@3VWffq%}O=B z423sLXWc-}fyCs~Jvmybn}~p)FTdg!BkZWAJ|xgM z3F@YI5h>Su*llMB3=ml#qy7CGMa){>?&xXHzo)#zKu;>RtxswSW!mf7_EvW%!d-By z|3pACp`1Yaxd`^3Ik#w3~d9+ zjv1sBhSwRHnDnfure1IdN%eHUlz9K#uZ zVJn*+qK6uf0tI+k7+wbPH3rIxVw(^dza$m@4uE!bet@w&(iV{W)z;L|f|Ezs7;V<%}Fjo!udgwY4d5z zYVo4u&)LCtZT(f-1)8vg$VgKM@_p8uz`^D+1Tdrf^7NRx)76F%XM-r=ZHHmTJvWk9 zeCi_Aa*X^q6p-jFu1&=)HPkiobqLe--^5ZfJ&cJDzGPx-2W687k0Qr0itTMElOz7c z>!2!HGS*a8WtD4^)6}=My^bv2iU^(SY?K#?1|7^tyojwSFYcl*ipkD>7PUdN>`z%Q z1;)2DoYP!&urm&kOddDx2ZhVH&L(8|cKwDNyOdQJFNVWZ+zuyD`pDBb2s^Ao?zE?} zp5Yvs#N16}vAG=i>x*q9AF68Y@}g5ecO+N}cBQ+hE`faek&;kN_ZAze|5A2M65iwI z38khIqkG22+ssWlHd*WqLMb=YVd3io_b+q3`ZNhX8as;RSZ zY!c#hg$pirGG~s8SSY8ifjNl2w;by0vr+D2ljh@%R3p4s5&y|O@Z=KF8gzU8o}8a#q>H?bpg;;){8aN((!WwvB@QaOjw z-C-`UXX-8uL-v{rME2E)Z1^A$>eFHlANg}M^N?i5<-*uS7-)SbaHQdh#8HIYknDYr z;;FtbZa>8B106z8)M1jPa}d3`7$15tbMxT~kb9)g-ZV8al{OVl0HsLRtBAwG7t3r1 z*kGD>^5&kRM;wK)ZWXPpvQ#b;sCina_RCIiLT>a=B>@SAP`hh{!>jH-qdnP%8JH1NGE;nDpSD(D|Rer)GCwyJFLRrr_ZJYmTRXQVm_ z%5WrG^TB?Vc@g68D5QE^N{|7Ki_i>sZyA@?38>5`ujDbLjh+Sf5iWgu>*Z1Q ziCnjH3)M>qWxdRLX9c9ArsXVN->}b599bx@@p*;LY88QK87Q~q%lY8w=t&j5wMbo4Q~O*rfgwniDR=ErTo8_ygpbZk zv%K1Q;_p;D2BPgH&_sx#Eq+ie*E_$y2y|al2ycRQv@H0AGCIWlIX0PQu$D;DR_DmWF-x26;S$7*%I`}eN*z1+*@$)gX06P8l%#!9*~0C zFOyT99hHYV?1s+crN>|*C}F`nN+m(86;%B;<h>ModL%^e- z4(~3DMDv9CpA10j%Ri)=f||(x+x-FMek7&6!Xa%C9*8sqEJ15)y$GrG8-BSD_&;Aq znI*}E9vW~ihPmkIt6i6DkPJ*KfGMlwVMIgAsA3H*`Ncd$_Nc_3!h(v=w3*#|gZ}CT zf6_Cx@<_$p56!(d9!Nh!@@Npyh9e1C$Zs-AC%|isjRS- z?Nl^>`CBk%tgeNna)yFf0yQtcJx~k3tU7Q@Myk*Bk`g-w9*2KeV!&Lz8 zoNOu_D+(WJ4w7iSXDY@cl)lFFzq*6y9&IB|p`f zVMDS8H(e-DSxA8a^D20yF>&rjPb~51X|o`eqVhC_gby}-@D!@z!jBb0&&2tkXIwHz zsIl3_#a;55I+ae7G(U&R`y%CZ^}O!0X&kGa1*{qM=n)rEUD>-6;MInu_v^J%;FFqn z{~=<8ME2c#zr|9JW%w04>UC(U^lUPKS!oN;`BG>>bMBf|U(I1C9_}tbYV1+;){mg> z0fKGZechYiypPYVY$BoX_y;veExvknoYR8=2Qd7&!$0l@5d-0d&Wr(|Tgjh`qQrkm=D)ykpGDL<>eEtzjlx$Ss8OZDlc(x~N>Ngz>0_AK z6HJe@&>raw4C8B#+!!cmd;CcZdQRv!SR++$l=h$q{KtWyP((Uc0f#DEDrVvPKn3F1 z;Bg+t`4C7$=>CQ+FCK3Q?o5_8T3lS5+bNO7e@#EN|9Qqa!~q{4g3A{le-sjyS>oYkI0eMQu1bM)zPQc)R8g(tL4+$v9dqscv@-EFB6#Zhn)?Q_%5$EJ* zW@pC_c+Pc#B%%e$ODB&Ybyl!W>#hsz?L1E2$+Gn=@QV1AQD+2Vlx^FU4|Bp?gqh{R zt<`4fHs}Q;h^5P@a=CJd1kJT}Z*07qN`GW{@IrF_d6{)UEme{7|@-3YLez8+}`$Dydo&dB;Ajkr~QF`<+WG|UlOf#r;;yVRly~=QM zaBx6b{iVl8eoaog67KD6GNB%B~QDZ zf*N~p0u)Eq+XBTT)R4eWnj{r`s=9z=%r=Y9(# z6F7wm$1h`{LWgqAE2#wC-oy&CvnoKLu`|KBILVN9KUG1G2Ij7T_s*~@?w{i* z9jD`M@{6XwRz(C1`M03mgib(r3xfm+Nx1%BYgP=g@gS>OZv}{qeutDN9o#I^JniuD z!V8szicjK}ZxUtwA(>67Y*mg$EVbglS?YUBd{9UN?M$MN3jKgul;5>(m#A+3es%Km zP9^!I#Y_)D;tP`FDyYRi7OeS!cZcR+cjL7m$?xEN&cC6Kzgva>__`R$YFxa{!Ju^} zEuS4mrt|xq@h2>FrKsODXtrHwhSgFX{)X1)1n~ui>*v>D2}5(XyXvhxPZLepm7)G~ zKr{B@IHQ(6D^h%wYUIT(#Wj%uN+f>6e{F>VuLSz%+m`Tw|cD7??C3~+@2-##- zvPWk2{XRb5?{D9a`;Yta_&oaL66w0$*K0h->$Mfk8rnZVk`LOy@%f>h+Z3b$dtL$j zd&egZc6PHVKaKZE9nM(9;CCLaBm_(x_8iwgV&Kd9>PN>ai z@KkF#{}<8u-={(tyTzjJN4JulBp4e>eF0bNTo8B1J4(E~sKMPndjHEHbLH+_w1| zj80D*A3xr;*|YJQ>RD}B{kp#RUgGi8+p+zgm9@8fx7H6|barPaF>W-EMJooCy( z0i0)hDfDR#&Bushe58sBRmJ>zsh{s&|L*E{kuFqD2~mE2{$R16?|7ZZp6=rWzdLWo-}b7#}hnGuRb=7hQ`V{aCA9 zrkC#cy>bvC66xtI^N21W7hHk-Jjp*w*`+?US(}?ySKg&6pP%lAovcpuIDYV(xcA1Y z1d=NDrY5p7G7XAdPt3C=Z#-JTL$llgDg-a^nl?u^LJL?F`%OC9N5` z$`ujtL1W`Uu7)1`65ksmk0BkZK}w7?KmRk(TSyH(f1xY`Cb~Xqr&EC*9RGTwF(^pz zinN$wcc3cV$G{+%K{#jjV@JI}6@8bLAJcJ^W>!Ed@a@sXaI%-k>%cX%IVAc)`4{ z&iY>d>r6_aMA)pJ$#{u)7PuQk;MpSb~$TAvV^=c_Y~#4nClu+PoSeFG4( z-TtO^@ra@lc6*yzITqG7u_Ha5&)0aH?E zXXk`S*zYk*RoXNS)y$T8?dS%gCr{+^9Y%_ej+>GL$Zw45;TQ^10(Z&A*&aSdfrq;K zpxohGYV31{U7w6QT3T0+7lS;n+4bYodw=-&Iy}fu-u0z~50$MEOTD!zz=HcP`trX# z1gQZvh@fq4MjW_S{;vn~uWN*-_pc|4F`G>Ggpp2Jc1`{8L{h;uUU31Di7S{&0qYKm zbdLHs-!o0h^c}(g9ajE1c7THT5z6p_{CutDuR9m3-~2dwJ=2MGyT&hT3Donw2?e%4!)qGs8c%$RMqh}G)=9k~EtD%~DuR?U;ib^lyi zL2S%}{kS?|EM{Ru7n0w1oe_y}|4M?RGM0ei6-HG5`z7os5h^qX9J-9f(0;;+>$Yo( zhoA$mdz6zBe*|^{zL1WV1&7%4m~fK+>#3C* zI9EZqmh!)E;=gVf(em%|EP)L!!(HYoFsu2ZUwKest6ywKBzx{bYiq-_^V&La{$$Fm z*K4o30w?e`pkxnLxSSC85|AP6^#DDGsfIcGqI4mH>GHt~`}1jf->1P?k6IArhFsGF z3L%0qcf(~R<+-8P+O}92lCvTAx$la@Jub?i9<+Eawg0+!kraYrV)o&{^VB!Ix(3yg z_F7ckmvydrvc-oGF}_fm{3uT^-Jz;@@D1mk8IH0?W19!(%3zv-FJHQQ;+8Tv>~#zE z+0OnH1PjAnl;no~jRnzRJIJZ;J_mkfN8ve_91VFs6G!WmG*9eQ>V$TIZLci&(tBN_ z^3FfQBG;t;+)K9e_ZK6>*J=uK;BPz+j){tS*qdqmVz*EdwJ2~8V`QXS6%ibht*?IA zK!Pia8F=s;$E~;k%%WO1$^&;bO-zaltEK@NkG#v%M2di8V?Mk<{5!V%=M%}}1=m*p z_ftAM)|7B2{hPU*cLVoE%c?+x0;>p{vCxp|r+5HIeFHNMRDqh-p7RtQ(*mrK1;bFe z3aPxI4viu?&6(jI*D+TrSb|Zix0y*$;R0q z+NL*fe=!Mc%~V*zkb@tlY^X6PCjAEk8NMf;-dDFOXuw|#iZ2{=#}VfG4~)LItZ-Gy=({t5!|@xHxbI*CamVe#Ml@|tpO2AYQTUHIL^-eAOnc#o`h@vy6gWD zIL=Z5RpHx#sLW>HM`MQFy-)S;=}X+q2IKgEOG*y5t9>uvf!jr^4vB3Lmj_jCD8Q~h zqKc?SNHhAcqC!HQM2}=JumNNZm((sHS}*oTamv6XD?kR7{?pF52tYvXec!z`-ewJQ zS`N+Sz!ORmREDg=J~uw?^_9g<(6dSCUgp4!i(+H;RLD%}k%;PBx`yY+pgpuis0aC$ zDg4-&3egraKy!~xh)_cg3*L((O()kgBxDeX&bn6sX8Q&_^As#O z;K(5+xK=8@TK~J!sEQIUHv-?v)zgvm|7VyHIb0e~<21t0(1y;xMN+0SoV*;YbTmwo z_CRp2MC!E4d4N~x8yK79R58Xc#tQcUR^)ylWLOdj0N&dEWGT1$<<~3l>xrCrW?`cl zIhF?$g~;5f6bfP$!zVe%nIB&evBZd&kk&eXetSej`@SQJ_P$EI_m(wxDbb{4Il9+` z!{SwnVqB8ZAEFVQ2;1TcJhp>-cQnJMMiON=Ne^5*F>kuS1xmZ2B^?8g2@`>v{PB>u zBAbq)>(*SF-&d1HQv$eTP}v{azDLY)SUhf!M2#(mt~QLy7YNBviW=6wyy2Xu1F9C- zFBW=*gE&!hazWZfA#k!YTQ4nr?#Xk$Gg;>G!jDu?9*huie<6u_Fh%*V*dkHh4f=$) zju_uOm4v&Vy>fef-H8(HDVfc8=X8Yiydd`F+T+QIK&G56e* zwY@!J5`RL7)JQtMGWH-%X8}c7bYpf8Qu_Y&M)wYA;k0tq zQ)1XhfYZtD5xV5>Ngb&ChcHIJc1h3zNtJaQDOI z{Jzq+Qd=tiEkX*2fn#80?GoNF!Qn(5bAI9i@0bvTRpu>JFoZ`~=ncK^Zp3RUzvsIm z3Z|Dxa(H}6X~+d3W$aRe1!up{=cPe8P6>1Gt}tCj2>+t@r9p{UAnk>oMa5Z_AYHCL z8?8ff;0t41$Jar2iB01EH9I@F0EaGwL{Yd0k*F*@@&PZ+V7fr3S=M{|+UcZA>ZxW+{J}2jmy7cn`R{P_Dw39m*{r{T3G5Q0Lc%TU&BT>Es%Gc82Dq5jp^4ZTC?F)wiv=s!J!PEna4lRtRi*12KdF{`UjT@=x2yJ zZ=E}!p!H@9H z#4AE&JeNeWXC-+t;}vx?MiQ;6N<)}JeGSNjB3`}Hqx}kc&nF*TuTgb8>Abbg1eQ2d z4iG`{*8e0x!AVMuJT8W0zzav5=GQBq~KKqt@l<#dzSl?epJR7y# zVuRw{2RCE>K+xca&rbMPEkVP*KB%pct^9^B{{kfYO1MS*!QQ$C00MMAUePC{qA{J< ztLKZ)+L84CT}l6scBJSd5xP5-r%VXrYEnRy1p;hXYu0E);@h{1?`cp)zk9xSc5cuV zf9D!B!Ww56cs?=9rwYq{*`yMdOFvvvlfz62^tT@?qAbb9J%j9f;TRd(NWChKuNiD@ zudir=%CaIFye5Tv!<%lCG^p7nP-74l)7r0xhRH}b#@lo!$lEy9lU`$bp-p#IGqIsotj7-U} z7|=7txP1l-J&jAAML`ytdb+xP(wjKg?Yp{wk*qYLkr4lxegSMulm(tpZoiWX6C9R# zp=gK@DiO8v5#XGc=s?H-zYyoX*&=$rGl6#36XE7ssgE!9NyEtSh%v``<=L*KqGx$f} zORaCJ%Gb@&SWFnm7{((Ihy?<^1_TDZpQH8S5oQqd zUQ<~L5Js(|nG|GJ)l+1&T(sU_Kp9j!n?H;-HmJQnQjGab9M29#iNuwLNLR^MZM%2Q zLpOKWhX?x6;PhYX`sLgU!9$pd+i@WLd8*TT*dpz(L-J#VR)tWMovTwRuBI zItr%VlJ|~31u8vc?{-|}^+;eyeP06dblj56szBL9BDFXvZqvxBI+fsrz7?hMX-?^H z0{}Jq0k$$kvzQ{|g;r6CpnBbxp-8?nUZ5kCRo%O65yp6OFw&$VdHtf!MBOCLUo6!J^mT5~u-(eI52|KrdoyS^lS2 zYM!HZyZ?T^+kDRsJBP62uf)M#*)1Biv|A|Jbn5~e?QujVFDiUPyj+m;?4yjmf4^r1KWZu zN+ham$K+KMR>r75@xtI9so=$bK36^s3T>h5irtFOgr$Ay-wq`Mpfp!HfR;-Zm7vVR zq%)oMQauAuGzec;H_iu6iG+xE;Gy<=L(JI6Gvk9Ot8z*G5ml@RB5QETO1k<4xgg_U zbqwhbLv`lF`b$ih4=%_dp$k1e=7QRNlP1oWFEh} z)FR*6B1jxrFm9}@gU#K=ps%0mtiCJuE&4HnC>S@r3nQYY*F_?vBP~XpZv%t(MwFu<64*|axW18 z+->+|72S4U&^!RZga$yYbo~s^-M`*FR_Vxo3ia@gI0$@QLsCn$Z{L)521TRXJ>-xBcH_(KP zG6FlR7)&8t2hjz*3VG6>id`A}J* zkD{^h@dLqhw@^Ui`9TQr-7p-yAdAMI|I$(p`j{E2EDwZ5*X3Tz3z5(DyT8|$`b5TV z{#BEvqldTc>P<3wP zp&*uVpF!i3vuBi=);r%<(g4L0l598mRi4pWbk|W$L}%UhVT5sB!LH7e#@xS$1)u&- z{m|P<(TVq39d(eD)v@(i`J-faDE6IVIXz0=sxHIneiQ!`}ZA6Z6VAcIZ?_1 zHx0=P7v(iABt-DgA!WEp#N)3Tzsi^U6=L1Io=@viD*YN0X^S1Cl?0o$WW3gRuoB>i z8pnl;f^+<#3*a;olbT&aSQy=STLVwAt?(I^X`ykv4(7Fkdp4pE?m5u z&2cH?20ee5CXrdbz2{?SOnS1BYKhLu3cBIdq{*%~MCjDAyxoJ)&=374LkS8{&2B;N zdZ@X2qMxPfzN+WqBF~?L;4j^5pW?=K&eKoU&7)<5$riSY1xhx?_=EzPK7ajcj#L5d z2F!I_%c?@`<}ZK*guN4A+jH`06;{o5RbLtb0trJL zcURW=xxY7!5uu?W{<-ggg^_(GG_c45TjTHs>lMspP#JKL`CTz7OOn6nf~^>#=1pgD z4>svj1N{`Cba>v&t6)a>^667DIH{&CxD3J9y82qahM;#XhGGS5W-j*RQPW#!@C`p) z90mgyYaejng)9DPj3zFXgu^pA9iN4hxvfWerUM(F+fwLV}i>n=aKYEei2 zBg=i)GA3V2UoBQfD38Is%yVYw?>qbj&pdlUW$>N!$^a>Y%|!cT7ts44o^nl}ewCZs zF+(D5rN+61Q$q3ECCsU8Gwo&3DOH^{oczifffEx(U^y1R7noh8K!q_HD^vz>wvX0v zZyxbc4HBcjgHEWP4;(NmYlJQx$`Q2xukBt4lcAB2d}Jp{&of0e4bK87mK%#POX)U* z9C$26FZ@A(`@spJxGD)h_Axgp#ns(1U631b#`D#-2R0rM0U5Cxu~kD2Df0nxp*L@@GpLZ)b%&13gM(SdCxW< zy4{>j^my#LEx+TD9-Gb@Rhmp7TU6_7Iwp8*N{SjFUUR|Pg}gCGR*X>#vDFFX_dk9X z>I>b|jed1RHAGM}MKE@qFJynB!Xdt<*5K2P82KQwS=K&Tjt&g}%*@3qBJ^K>g*+NO zn04`B@?ys4c@ms`_f?majb|a#7#Z*L9ZN05J1I{pMW!6Uz+NKqn~z56JMC^LkHt}- zKJt7N(0kin{CtV&3VG|TPziGz+6~;tPI&}JIA+F6&n-O(!J1G|5S-gt6{|hxX)-^} zu?4rEk-L@#$Udn$=4aHn2uD(Z0wzT*=Li+|-QRSUMfLTv5wBikS%XyN&a~kh+w54+ zBrC+adR^Iv%H0;ZG)@B`0d$w0((9qd37qYTV~1;<=jw#>xGO-H&9&0Ga6!R?6K$JZ zmsZogb3RJ&DCmpQlM5Dgkt;m|RQEW9JpV4pNa1m*ujNTs;AK%MiZkQF;9cu36khtM zetqFFCZFuP3^D9{Ag11s`d<1hyXHAbY&VI7C!bh{C#_S%Wbodd0 z23Q2UN;Sv+o+QaWDGPXw8>Z{Hs^}B!A38~fO7R$euyn!8LPq;CR5IzRC0Qh!L>Mhc zAGPUoU#dMu4u)0XWp+1J_eW9eH={)BR>T!hhIp_xBa+K^GFRH)Hi3@t6ZPY=cqNqg-V;*L@3 zJuSaIJwqME*d|Ogc>*GrDl8{SMiPK^>(>X3Wvs9;?Es3z_zAh#Xty_l8QQ<(wQSV3 zsxPCV=&l)%1@Cl^lNjn^VE}@hmk*)>2&?kk2a$O5hc39y*X?ybK)YE-94`W1<}zy0 zTwi?xssdtqF<@+JSV1#VK#Z@XfM;K3jR&|#sK*(V^IAmi@+1jLIb4qOtM~_TIV_9= zAE!e2$ko*?kGyJD4m+rlf+!XnNC^}tMRB)J6%3v6!>J9d1pEcW2LfjkXNr4Fgg>Km zLhpiaJ!k=1Oh6lRAtMx51d;YHY(%_RmIqk4ciZJVmqeZa6;5b32_q9PfB`jCd^03q zn<;4MG2D!r3qaGG0X&71h9=Agm4u^XI(;MfyVmdQnqhXu&vMm&;6?sV6RBRn6e`H> z7R?C2>;ax7DEOQ(1x$LYTY|lw#qAStLn*V4-e8zW+ei)KZAOE(8*`{sQ|b5}fu!mJ zZc>Zo`BeRFWvm7mM1|jkDD4M4+lLM7OL24zdK*GtR8!)lf!=-rFm5#77yW>yWT|nY zs`u8@Y*F~!b^^s)Vl4g6aZ7X4$xey;>G7VS$pBD|ARdmnS{n1&c+gzDl?*iP7Yg;? zIKH@pL{xfk@LKa~qi>vA=K!c(_01yV!;Vr>vgA;<<_dGlGL{8Y#{7uxF#4ky*_An$ zw?ubz8tRrxWz+#5c(8LPGKU18Ip!iF#UC0daPm{Huqr0R^PZ7WeUiKgHs(ZU_1k3) zIk951`JzoK0Ltjl&hizjH7O{pJfHx~?q>_V;?E#ZFvUMmFG~~v00LcOZRGDBP&?0; zg#(&XrO_I|&9aAWXYeP*`)8%Q%Ogd$bNZL>vfTR8|8wEqd30 zjTf8*O@-5n$7#3R-$2lDK~k%G;0Hwa^obK@>5-`m>0$@LC|Bh3=Q|%-E&^uW2WTA> zWfEedPyn3-VYv)*qmsU zbrbLBgFgcHPY!DPp z&~z-eGivZ8PXk#;_QX)%H!tAC%e(z^&l?C)IP+~Fe7Ue`4F#3;X7$f%S zja0Rw*Fz_NW+;*N-!em=bpZg%k@V}kz@M0uF3i3sR{Q8#pI;qoa)I6WmB3Hz0Or!X zR6gQNgx0#M1)JthjdmU7jR?$ZcRDg^-gCXL+Te`^EO@eT+xfC8UVAGKbqciv2;dV4 zfG6*3YZJOuH9xh3Snz7){ro?VhXAr*>S|qLeS^*Z4H~39^|R5pV%)ps#h_R-5Z{L> zJmd}02hU3>E?tNW9!hWGT<{t^-((!UIKZEMi(WE-tGE#7DFCiR&Ik=q2Kuv;O!Y<5HZ(dd=MqZ=;<72-*8_TJ{_O~g)nd0}sv zzdL6IC!01-sxOmd$_k= z5*K`&MU1-sI|1CU!(*Tu;WK*GCDvrrkZp#A74vr*7~c+Q3vGj;({XR?Eg4S-IG}=0 zr$4$?%eH;vYjl$voosh~xZYS@t$&r5nx!llvzih3qI}vYk97Z7Z?yp5nZl9zSn1e- zX(nH8)+2=hi5PtGQ*a%IYqb?DHkO^0h#8fV_bXfCGUd=jX)mQCWeP9yT82&#U+(!f84RIeV?Ux{`PIBiPAu3prsf-#=TCJ zCk-XFk7hfgTW}vCWT^q2!w{T-y{Wv4rjxqp&gbQfgSy!>tVVXrjA$_ev^u&3fQI9s zjK$j8Hs7C8vYybW&<3%wv6Wk0h2(qeGT}*>+T;riZyJ<4XHYE)MUM*g)!}b?to0`X z=(MDpbHxGm95_Dvzh;r*%4!+^^VE%vjZxi0#(tFzo(Izp`Rj0Zu<)qcC*B?~$#(d5 zDn70V3qhYNd2Hdsuv6cVH%sM(9SJC-gs%;-C9R4eUUA{-ID2iQPYu=gUY`MeTG z#_?1z6g~O{Ec;kUcI(kPRAj9%bgJRCfC^S$AV{MT6YSC)kQiu8pxgnVec$yktv&r6 z6CJGpwzL$u4g>}3-gHWDWui16WOh|#n*F&Ux3d1w9D;^~_#ZEuY6I0R?CBpscYYHp zsn0aK=KkY{3|Hwp9R=fuuhj2XGtHi~?vRcWKPxq(SyXE*=ZdM|SD9`-WtZnffT1@d&$nT= z5G&lf&!olMrmf>E^e_5YZ_mDP-ImpKAW((SICaqCf`nk{>#Ve|$l-`UXd6jbCZJEy zm>?N50U_%x-#H;>9s61sn6UFKBS#wt=X85dslcHO!DZ+pe%U}klIbj z|3GS8TkghbKe|E1iiIhxd{3$>IiM|F)I!TZ-%A+Nr?s;s}lr^!@2RyAg9l=G^*?wI|PQ!2dsi9f5lIFSsRF5 zWJg30apdQpz;8)UNwB8*S-&bZ?u#%*E3a8}= zy*UcQ4gwd$Jpw{E9{>uR0RmrM6v_$r0Q)BxcAsw#8$Jf^0b|%}EXLJU+z+gMM@*Q( zT?h-C#As|{po0>A2kw?bn@nbii5iFj8)YAj8F#aeC*@4sSR#eyc}Oa-aLJhIAa(VO zJ#?B^oiB5M5tUwtU}gY|515r!zdUO&T5k7-C8)EvcRuWptimBA?CxiMH=>s$diiF` zF?RSSEh1Jp{Y9##r1K~3=E6wD{wvTjJop2u@1#G zVGP>Q3u)S?%5xQST&#%1z&vRI1mafMV*5nN1!`=u+qu&;J58P7hFNpuLRW%u>7iES0c6P zN`C8+Fvb)ecL(YR>X`nKP5~ef%m_Jo2SFcz1WAe$kLe3wLaLYwW#J*{FouH?(Ed4C z$G||!S2zWKyI;}EXd)Dw%0d$rJi8=T3k?xed>&SE)|c7mS)-&_RZ~IpQ?Lbu5Tmp_ zS@2{F8rC0RtnSV*-C{FZG86XjIVeAf=x8ml^Z|nJQ%89Gt>@2I3z*3u1&G5Ve(dBe z`0$fHy5FNl``x4PmcAnS@Cse&Z7z=D-?ziE?GXj}VO_o7}GmPyMvU?p+j0 z{p{c;OT8;+!kcTP@X!tGbo^_GgD^Gsy#`J=X-5jMx!zr6&lm)@xZQ9P{7flnt_U7T zzv$D&H9-ODC!{lo?Re=E z@VD*a0?4c4x|GFAl3Y>2J%(pwRw{!a$4EJN*6st)Uv6QL;AR)S)#jsUx-i9&xh*QI6b6%q!rBJ*e*JxIj z<>1SlBzxNoMMY^dYQdN5=OE>O)s?&-0Yu;zOKC91NH!J-f##I}U6FeszmJ3BTOAO* zgO7wR#CI)Ik^{j`A&=XCV06}gvFC@6!3@DYrx1ztXBYiZ*lbwo+T8^Gf)THYi$y%H@_V{`2jW+vnfo)IETxr(gbH!gP1iV8fBXfn2iGZ`@7fi zBnsXw@?PgaJ84aB3|QA+pm;Db;gaDl!f^itsgW{-XC?J}%9R|*ya@R8cIWy>+Q(xn zE4l>=X5%9`28#DdiLdhynum)3CnoK6=W3P2m9=v0cQ%SMfzy~S)ec&8mJAs1@aECw#%eW@Gluv2ruyP^(`~gBX`NM4;y<4tPf90EfS#Tp70@AB zgWvPcGV`!9v=XA%!onm}v8fi?fRWPyN+m5ClYzglwk)FenP%f9@v4>#6L^5NCz-ar zrVq<|`esV?u`C#)6mR`3P1=gqXViSNSo%izajftl|yDN6EKaD?pDQ}meAh)3% z*Z8jQCQy)jjN9erS6u;{Six9|+^18tGtuqscdiGI)kDvrAz}mzPcZqtr_5krzAxzm z^K|we`NKWm=32rsi_oFAMw(KZE>_mG8;%!JoLedNb-n;TKak6O;m403d9}3$H7GDL zM(LiG^v{W_ih1H>@p9F+`5URv}pX!QijrVP7! zuU83`(#-QH;}s%-3hDzN5RB`*(S_Wf-B*YfNPh=vtXh?!ct&J_3H2l|s3cmh90^FLWw~f6 z9(M7s*g@cCyhqs0g?OR)4!|7S!xGF8IGg4;a0=ApqTh3tfYm*kPCECv6nI+`uOw5N zbN+c7x(z~#kl#h01@2m~JP9)eB5DDa@p9o5Kwi{Y7%AkQ#@VrFabeP zbD*|p3Sh+*P;S0uwz}vv0rnE#aiQrH1!N_@%T!bn_&6D)AW;4% z$nZcla5?Cq05);A;c$C4arf=uOW#O~zSH*fO+07*T&_^1@gu>gU@qP+yD zAY&TZ>kZYMrj<64t_3a?tV#T7UFxU==UV$Y6@x~L8UlpXwftJCX2NvU1!u76boE*< zSC7+!2~XqB-VtYSf)l0j^p6aL#p8$;aL>)esBAYG%Rtw{@)B;|zN+b(`z)S!QgV~E z?wJe?Qt;1Bw8})Wk<* z_#^dibrCrCo0IO0Euob8?@Ob-I=F?e?IvJ@KfPqjilTT(DXN}OLqjf5N9%=@`Rji- zPrmxjtPHEVCMw~aEl)`A+m3TrB_O2y`9QNaCh)`07;N8Qv5_D~1E<2J6yN~8HCHd> zL48j^rqHB&O_yT%ciM(w;PC~@jE&aSTJx}2o8DA4z%1tyraT;rwzNZ&xD72+DC@INI6NJ&?yT~soFSv4}JwG=1GOvjQVv+ zREBmDngd@R+SMzT9&(2aAJ;6e(#xjfJ1OEPkuss-T)weufVXS&KiPWMAc`D1|Bf;V!S@(P}n@661UpDjcu*M&$;yH@z%8 zMD&G{M{fv|=sE8Q|Eha1EDT#17D;J(C(FG{bJOvKMYJ^W#FaXjax&)+4#qo{%&K0a_%+ z(B!vX^_}Z`c(UEuOQATwNEFj|M4p91%_loOyr7j-~o^xcr#8TI){k2VHVDmrNB7cys8-;N0dOx z%nnK>2p;jSdgD*_KKrgV_7u}gn^;$&TU`0X>I9qgbk8NOX! zWxfFHAWVejHxgJU9X&GQIPbMjSl(oJ!1m(4Fm{1c$a1Wha7Nxk@hjIi#h`uU&2-3% zl9vbo%<(T)OCrt6=oaxaA)j^0>i|kgl(kJ+Fl=wGaPB=ZxD070!=0o5?u2eSo|@3g zw0PIFU#p47VR5Ob~Rk2)P;k zi>4$|wBIJgSK@{$CH`bR!_}Y>Cmq<}M3wrKPz67-br$s#KMZ7Q{;J6=?LGeTm zbN}|10r`TdX?5j~#7p{VtbBVj`{x*GuG(ov*PQ`|AA(^TSOQ>dGrm{khD)NpX{=mH zg&%>Umv27OB#y6S!ecM6iv56Yf+oh*&;%lwVt6UHN8Y{yxU)WIcbXOA`SzI(^&ABKUtNhz8YO|j7q|PsB*6PA z(jJ?QX<$st6Pel>uFz*()m;!C#RYO=1_{Iwn6II;uMbXnATfDA@S)z;`2{A}m#&O< zwDH?0Uj_jo;Ph~sphqt_BDlsj?iF1d2iEEp`7L}pm?vBv~CF9z4;bLMuGeAg$5)seFlAcf47}i@+a>@#D@4A0%YsbFp z7Xxi8^I0$QkI;f@Rh&5F;|Es056yQw?G;`Oas7Gg^Y!{j-aPu0yO8^ zFJTJuv)or0{9_aG-xC&sB$^cE;;RTn zPfP)YE|v&iD-OS|2e_3AS)eoo2QvuurV5#MEC0igwJ#TO z=qOFc(Q^fIW&)B5=2C%eb06<5u-yPMg!f$7HVcLwg}XYd`I!Wy&?oIfOJ~J&u{lcR z@o%KNk#MkbPZT36(XhBK)~WX3Ud5BK&N=t?FKt9jj<}{L-)zL-LlxERZH63iB@;iz zL#-u^|H`1u`Tu4>9+K$sVsD+K^G$fupPX9+bIvfcLxU=pPwXNrGcR)$Ym}DWBY5r? zzuuh2bS+pN1C)J8ymbYdBhHVNcmD7Y$fY}PKm-@eWsTOpS80Uy6HnOlTyt+aT$8aJ zBF8D@-NxQQfldbx7~=^;(HK&Q4E9kZ2}=oKFQNXq??N1fVYHkDyU(WiIR+^Hkd4{_ zD$m3ZlE7`16(C;cZq9B-O%p{@W(wp1k$d!_NUBot<|}yT$@NdZgMQbE(LhfP`$~^- zSGdOMvZV#%EZH;8^DT_S(8iUiqP}s^el+L${789z6gD69toI@9`)AG>;Nc6=bjX*_ zGr@HPGk&AG69^3M;dF7{Wu=EJ#nsexia~3nl;tr7NWdJ^&b$ zvOnE3LE0m??h;2FtUeBSmoBi?PQ9h>yzU1k(spJuy)nEO#gX5-!DhYj$OFt|y6|pu zNr9lWGbh8_fVS6z+#T3i{JhI3_~2jXz7X_uC=HFhu+g`-0|J40Wfnk@)bF32NPw{S z>k9UDnrZsPkNAx{=*+3CQ?Ju6&m!<;WToaU-cY=7 z=)VZzWH0X5FRSaLbT?_0MHC6u@w*kygYAyq zC54|AFWso;AKc;pr1@xBlI-ITfh2S2JCc#S0^``FlFC|_9&YO-9EOG%Jp^vUc)8Pk zw_9myf?v4!)A&;ZqSqQvMbosSUTLHYiB>1yI+*U@2r3z@`$~iISf2d)cHKDdc_yu+ zwB{on;UbgD&bN-Vq=Z3l0|erD{f6YF<5!$9FZ+Bcq-?SGrW9zIFSx1J#{-Esf?wcN z@#o?B_YtpqfL7TD(EmeaY*q>aQX!fW!H~aEq1th;0oS=qQ4{tI!gJc^YNN;d=%x%R z#l2s78@vzjx0R2l)d|4+x}kN#NlV+^d-uZV9$Js9+JsZ=6NVWs03pj27Rs(o-gu+4 z5f9@dC&!2RO0T%4rms)1gt@Uw3y{&Unmr-3L(Uun-j}68kX3S_3jk{}mXcUKBK5jm zPeIv~WfYDh*IWX?;guUVkA(snpxDl}R5hlG*mB2_8?^BT0i&0lWDET7#$6ETD=`i5 zSe2Fd%DyMlXErY)nWd4|7*Z)rrfqKzYQsIWF93UJ)g;sS<$#prouP}1GKgqEIA{E= z+6d^!c*WtNJ)buTwvbp5)GQ?c%da8^)ZMy=u8OG;^spY=8-YGC8_Bz*L75Ow|C9ZB z0*d`k5MlCMtkAxu#^YHmw3X+Gji zZGWwJp3`e0!=^4nz((E_416een^%uaI=BlKsShG0IV5oe;F6DxbtFIuEuIXRron;b zv^V6u=giOBUy&9J`|;*yzG5zI`NkVkOyeHhV{t$ybU-n$#+jFsKR<7jwV;UV)NC{5 z=H%Uj;h=4^VDn>x9*Q2(JPH@W*!?e4J4HAf%0ZYy%s-K%zi>JAI# zUVA2UWjYm25quNZ0yq4^LTDF3jfauC3Lv9E$R~)Xf5%jL18HD7p^D2&R49QYUE)tmQl}r*__3jY4Mk%BwKw; zTFr^~C>hok!R9Z+&Uhk4>=7g5lF)?^Dubx|nkLFs#d_H%yr8Q+;s0`(W zhW%JC7a+@=VPIlpX)8&U%gw1oQvU%Dv#kA60ewz)3eY z7NPjxS0oJ>!J#-5#75B`V^;L< z@e-G?F*`es(~S*8X@!-U=OSqhkXi|5mU}eMD{IcL`GGlQ{WT7}1@|{Wu+A8fYB!nu z@ZrAt@M(~eUm@)jA{4(RqQ&=n2_g}i62s-gH)>j znZN;v0WZbvxdnP>Tr1C%8vD&9P{HJ%JhF2BnMdfmCdmIWAkz=rrY0_6HS7KQRp;%@ z!%dK*2Y@$r?x*SxQw^_Uf{T6DkLJ+x$jlTh=9P7*Hu7RY7bg-76vN=f>&$M2oF|Jg zY4AtreALli|Hh%4PuXukTfrhcVFG{x7Z*zRQ{y*_M<05qeRKiyvb$R1R&N;&&yfym zJlSyQTz<{6?G4sJqcxTL6q4Al=DnnKYfD6EUVmpv^mOr=rh$CFM6awOK&jqnP&QvX zd2)+XRS29#;u_~5@z&zRi0k^>%k{Xf>%q_1PhI|kUihMAuaC-cn~qXc_PWe{tsm%^Zx*mls@DUZX*ewJMM8x|lz8X&; zB65DECrKPRV%{F-wRlSKp~nqaeZvf@%?4&kTTuU^xX1>2hVtS+iFk8xxKXY9Bos8znD% z{@1m^a&IBOquhQIul^tcwDzYV8KZ%RbdAs`LQ~VJO>?~Pu3P`XQ0cUoZdUnJ?bhFdbA{sahm-y1hjmry z)|M#|$>Pl64vP4>fuFnwUfK>YFXt6{W;3+ceV)m3nnk4#dR;@LVsTHORX1kSduSuZ z$N1)(kM`GN&zf(FZB43z$ASc3THRy1EGfPPa8~-QtedUY__!8gSj+jnKX0R1>-FBb z%APo3(YD^WxkoW_;gU^+(#hjXfPf$R==Bb##K#Xj^U0n2;_~w5`v(zGILI6_=la@# z?U@&Pe3bQKGV1K#9}0E9Jt`;eTO$;~<>IK2G4T4#0y{9vbM-u%C-_o|s~7eBGEUd- zNaAE~9+c|@u1QkF{p{Sk3p>-}4{U?(ORe(m{UIA4zKIgzIEDlIpcq11t&F$mrSA;| zyETcpvBinjJGPT`8{x(#jHiU8E@D_)e41^z))>(w5Tl>c>3GH)dga_HSyg(>vhd3c z`OB|2_+q7l=~0SzZr}c~@Ur4OdTS+~=T9!m=AC!Gts>t1meQcdcp=+5BMN_5a=2^AZ9Ss~YSodNa#u)^GncQR z2(X~eBD-zu;6y%CTa{|B_lI)QchuT%g0gx&D>u=gdty;MC`ub}8Pgv8T^PnhEIPpN*9z?VFkC6zF7HjOp z!*#2{3iVdkQSS?o7SZ!UVhr+MQj)clEo7Z^jT|A^Oa5OP^X_>A1HN- z;@R56M?_my`-8y$7K>nU=!3rjvQF<9IkxqHa-4j7Yb6*rtrS|$j?-I<5fwd5*r%RE zO)7{h${9A;iyu>MIOR6C##E&B7~;MG+s(eE-fX|ZFWq_N3a>5=-8$j(#=-onM1QSQ zRoJnCm5XecSG_DGSqU+dLlaj&WzRl!@2?3_I5H7c_{5`rOog4r*J}^`!~>LB$I<3B zu~Ct$olnQ1c&JGIPE_O^ zE)q}h-@A8)uE!Rudtp!%@r^&OH~XB>fL(sBQ%6y_w$p^)+I4BvS$T@ypdZ`ZPwWN` z30ZS9G%l-)ant$~-Ca6TYI|KT$N7;k{UIUR$BE^CtB5MXECPys1f%1#Kh4ed;HG7v z!$|UjX?dxnrSro9j>3t9OYfF747vZ3UJO#0{=P1b; zMc7sTqiCg$jiC*@{*jJPmH;IPj2i&RM9~uenirz*x^;Cmj*R$YlM$g^9Ick02~gYK zjSDV~Fayy|0gIr+L&()&u~m_vrn6$nfN?3|)EnItM7sFqv(fOq&pXL??`DfyoLE^; z{abZA?!d)%9wK{v7$o(;UBduE%dWwbg{t)g#0%>l zK@!1qkk!kx7e*%SCPXGM=8eSeSTpY4Wg`1<$_;Yu(v_`KFCxqg*p%^8)7jRBbfm^w zH_6KsA03(=i+v6#RTO>~y$XL{$A&P_vcV}ei|hP5Ih!1jAa*Y*yu9RGj*^s}jjedK zG8YK_XAkrwWitK<;mWyyi|NWxT@hN%=^JyMTzT^-S-WknjS=cyZh2@u|AMd8Ue3I* zx@`fR+b4hoH9r>#QWHu`z1@zMKLr;@tt7oP%OG_p7g$zh@(noWfy z`#;j!|KX{#$NyE5%S|4E>3T; zkll7{)~HnQA7*)n7#=)$puM+aadAb)xJSr~Bs-i!U*_tQ7~@Ds>DL;?xbW4LmNaP2 z{#oGtA;~eol~}+y`*hqsFSnSQbi&Nb}RmP%>Z@yhbq-00p~V1LlS z#+sn_H%gyJ1(( zyY^*jK* zb@cpJ!cX9o_P`(ZzcjdS+>;t2=p;$hH;-se0TZDESl|?(beO>w<3?S0V9+#wI!b|d z7?BEnyGsrvOBl1@RohpSAmN1YgT^;N*OLZMVGa4Y+Evs)=`&MX!crEHuQ@BfVbD8= z>(yupIT=n)Vh28k8>^5BbuJLUli$Vj^Im)*x%7x1(^T!l9$`#>E9U#NK)-q8vAwaJ zpBNaQ_M^xjg;sxEKR(_s+!&O9u&hKQVj84pZEe&KkIZYoxu%KQKodWu9wwTJcRE^_ z+Su?3#oY!Z(X!ZR1Q>%SBQr+0F*6o-fs2pY5CCV1hS5IMGl|ou9pJH1V7K0$SRZoi4{tJ#pQ_t zbNDeyxTpXTO*%_|ry&R4z-VrO^bdf7kULxY;y5>OV%)BD82UHx-NLd&yu-`OA8CG= z3o{2f*ko)^a6#@jPfq9O!4JZ|UkmJyLWZDy*5BS6jfErm}ZB$$*a2 zY$Vqq6G>pM9VoxyzMsaO{U|j-9RTh-RvB$WmHxS*gC~Z{y@lI;yrv*Mqip9s>J(6J z)$-qhj(!p*i}D|Y=0ahs zO>l&nFe@YZ{p^k`nScnG6}Tw+F4Wfa2UqbYQekM;*>FhkNxsK!qt&v0J`2cH_Btua zCzFU~X722#4hIfq=X`hKii@!+RVAA7Wa5fgkoJDHm%TXMgb|O3KH$2@q?GNskXo-n zFLY*HrA;z+PIG7bZ*oNU?AI4iqFNMffR6R^=}Z+)#6YD-lI26xc2a3Q`@Hfzm zuE~U{`?*KBR@*AS!!HdKJW!a!nG~Gz!=*6{jjO4mGHMV?X`F@s{g_0P*H4~)HPn8s z4z?>)_ueza(kE-ReM6*!`7Cr4u^=Q}$mgiW{&Q8Cftws|wu|YSVNM+$(Lpm3!ytji zOuwbQN%t0Iy}3F!6)ilig*Hf2yo+q3%B-}IG+YY+CUFPi{R?v_w`T+IQDi$(R4c8e zwAX1zLSpLF$^mLZ@-Z*cG;g^Vo5#aH2@Cn6H&74r^DpWd_@VF`TAV7nFopuKO|<&4 z)tBN&2S|kMMXu-@DgghQyxl2FV&6-OiHXn2{(h@0smncaiR)v8FFom-SJRL1kD^Lv z8TzMi%m(==EVBW4)oe%3wP)``w;qx^&q4hXke>^ZFFRMFm>AbB(WPMfbR$2o+s}igUYa+Ee4XW>2VfJ&m+2by?DXbPcFdo(df8j z`nR8-{+Ma=ra#KI3=QSSn1hpKyn_wxsH2BRz_yJvu-lNIPi`C8S%PU( z_eW~Hi;s#^F(3u00AP9yW~9Tg>dA%4-kt9iAjr~_{9(?@lJh=SG zUHHfaZAO`d0?=&!fgfBPFXmIr(RQIT#efj_K9 z?&8;I(%?71g>MHmK}HOqlePxbcjJb_K~g2SY)yf^;OpUv@k$GrJ8Y<^;IpqwK-`1A zsDp_98`LSmN4~J@1k!>28{>5qx2XpW>bY}YyQ>0j`|P_JfmHb5Tgt)F(UM%KnACd+ zpf=5LwLgqoQueRYv}R#2KlypEu#R$P_q zQe&(N27eTj6v1K3gUEW2mjN&2ZgtJ!2@K800j<=5V&ZifM35arxY+Vp|=^!=P%=*@VUkGQBI?FZTl7%g9$LE zgKKugN)>*Ukk*$o6%`J<4<(1BB3CO?e!cKJ5rue;Sj+Yx&Q5nhNpy-$3QO@%lB|09EIh>Bf^s9y#D|WIO>v*PtzGo-K6C z)HZCpm;yuJ7H&GaH>HP|NU5%m?<72vwnt-J{7Di@Hq3;b_4{tZ5aYfv&syApX&wwt zSS(C?nAaF-8Nkk(p&6Q@w)0C#`evGpr<%%dMlYtM7^$>1YS1^`0`H`f`|TSf@D6zh zcf;e@A^LvLy`^j5aR_=}mC`c<;6(~WtoNFf!jbH;aiBSG@csY0ARaPiX>^{DGO^i%h3Z6NTM+J-~+Zi_}D1 zfpvS^#7RWu{GyWXUuoBqae3od|-jJ7uqaNJ{Lr4Et*00=hYiIt7bt(-!>h_6+ z$yXADA3Jad{U1!~y+vk?)Z0JNaQy~{=kqJaGf^1x0q0GYwRrT? z(Ip;c9Q{HO0%h>UrLjgBuD}rFp^pX{>#rMQ2#j^?{ha-3Mu`bj;b_X3+JtkHW%zlm zDCnW97V1DMYnhsLx$fKNo2Br%@(vfc1rSR#XgUTJ13x>+V9ZUXX0i$@7%UI+Dmr9w zl9Yi@m&~K6G`0PABLq$POSh`>HBxd0BR2*f59jPc{tMj)b8<(ZkO2jCBlx3(Rxd|l zez4*mY(UZkzI7Jd+EE1sOf4F27SXSU&Yir+ z&%d!crvpr67nJRWlixfQiU6__w>v&0dI2F#*Dw$9u9}bls_1Z5JBF_mM4F}=a_BAi z&U)vUAD%^2k>OPSgPIo`3I2mtug`!RmE>u&kGo~U#H=XWrK{}1D}NJ4(As+&7l=sH zTx#la`m|_Ux=PfS=es63yG9T9Bz75}^$>(6Z}}d6n~_ZTXA(p(UE~o*rO@6i)1r1C ze}9+hbta6l<$@NSlXt+P{tmbVf60nd61LflmBYD#ku>ZAKCUkW1n_#s4H#N?#C`{W zC;AN237E1r(%|>MFqs%=y;dT(O?e{= z2gHDcD&`&UEv6+!{PneT0IRz`gz?g5J32XC{P9r`D&#svjW5Tv#MIQ{wb)`J%vc}t zxNExVI66}O-Fl&jmuD5j)AErax+=ZGseu*#M^F?c zL~lAVjv`IJq5fW2!D5ZD)2N7M-rl7?vVf~+BUbxpjJdIK7EZ9f2O=ZU?lV&`40I5{ z(D!z`m|6Bfg(GQ_Q$(THfw}XBUXvv&_P_4>VI{y9m*v5DMo>l zXHnqbw#x&OAZ8`b72?W?qE00c$3Vy+0M!2P?APt~JMMY?spQH|+0E8pCZg+lW@brL zOLiOI8In5HA`Q2`V;dypI==LJ21mL{6h6ARVDMsKlFNwkMe6h~MfFp@XI@&oqI|4; zY12=$X6@*h<3m;oG#-@JtT>K7{-yiNXV~{(W;m-zTVR-2L=~=<_fs|a?iE`F&Z9Q; z&h-{n~$Jzkbr$3d!)z9Xs82wZG4%KMHQa0Ph+UG zk*LH8UNrxApx}RA6)wN)ZDZzO!0XOYJN>j)p_o<#a0=*+47#Ry<_4| zD1+7%nLKdze%xSP&)B#*Uu85gbF+`3cRQ6ABY%BknYRDI@h5YEUDXn;sq`qYCaGZh zyZzd-;Dt&(K5+BcsD+omjp?k~GlR3(8M+u2gh z$VHzro?ur`6hS{l+WgAC8rTQ{a{rp(l>>AXRuAf%wX+?MqZILxS=^dWa|{y16~QXP zNRgV9sv7b-^<}PQ>rn2fa%M(`G&4bHkQPNQR@VWm3f&+7!gkc-Xi_k2Dy4SsX@AGk z3X4%b9n%#STm6%l8LEd6nvd@Q+qRrmOeJ{vBC=z^d>cHmFM>MZ-vk2|S=kLP$-i9G zL$?Bhz28WhwJ?PN4NK(tl7)tbP)*=p_Ja75-0+_)UkbT?5bV{qxTAz)_;k`H#T7ks zSv6J1@0Ad)ZN3Nj|dADspu`g_Wl= zg~!evi=}MI%>3XC9`AdkGdce*dE)3Kt%AzS$9r13>S#WH*w4oQSh=F`@}X7^lO3ry z_6O#6%KH@OjjeIXTbmd#fC5u+W&#xgr0-a>I_XvrH$WHP(H z?;j=AA{9ZBn`BjvFH0?K4MI~~zLcZ88J%$j$X*MZU>bZn7(pjr_&2{C$Jv#mu(P4Cf~V#7rGeL1 z(D7fYpO2+Q3N}wqyHO2Ynpb?QQZrvUa}l@{(+2k7Y#Fn~=ui7koTExVE|B#3{LWTo ziqgTkSzMFIh*7u*^X22Dg|eT`2H7!_^b*`(n@iqipG*JKU1ny@uVie@9^jCd`#Oh* zmb^MU#Ab0fORMRGz_VCByEB_xXnaF)`Sa(53o>8x52mvk94q=JuFU*Ej~(D+%1Go; zi2p!$QriU@tGrhh#P<22+DfJx|MH3lQk&SLAY+vuT?Kq!?qb3^N3!`nDy=A{$9)gD zHh||;p(>V@pqrW%TgM}N^PAFBFmzY{wGcs6(`b^t!Y6m}XjG9wmSEV%?UuvtMY<11 zW2xaYd#`#s^g{0#HQyH#XuJOgjxKe^F?8QdN|v+)=7ug7F23~LyoO7un@Z0Hp>L&i z8GK-J_AKIPXqs0GiwTrreM!%Y3rCL}^=6(Rjh@(s29QQldcYGZSQIQ+Ab(jzhEMh!O*jW%d#LmdL> z3hPTr?)UbP-w+df`1fj)Yz97_RE?DWLaU>gSAnH5W=^30bU0b20zlzkiT2yUYt)ET zDvOW29)R0@o0gUwC8*9)5Fu(lYY2Eysl8$1-CZ0baq^EJv>`!aivQ4E4QDg6 zyyj#&Q4~%t(v6-R7(OKi68Ea#mpO_t7x3dkQ}Vb;1u-JHnDAtaOEAtd0^rxCVtUc7 zpx=ZNuwOVIaO+@BNkktg(iF_#71QS_4E-ZsUHw~t#GQJjOx#s zNgGxuO1*^qpllr2gPcVXMoj#m&X+fPuk5;)n&AB#YI}mqsn*T87iu%_etxUKpo#2J zAF=As_Hvf+?yyN%i2aeKCbsC+_LJUw*gwxTg zQwfM^-{@11T~AG;UfV z9vk`LFu+n9!795K)~a2!RTXwoO~U?*rTHBgL_L8>AK3e7hU&uhd0I>-Fxs>cw$ED8 z57<`p$g`F*$Or48&mdkD*DtV%dOdjQQ^&gh&ezPf`fAoo#O|fb(Cyo+SGj!55=6m3 z&7TA?%=*(e-!UuHC`z;sDJI8)5izyO5Jds^S0ccY(6)VFz8>~&w28^y5-+|&b*fqR ztCOBdb$<*RD++zD?382G`%1KwR&>o!D6yM#84BA6p>{a1U6a2{T|%ppr&W5TZ$Bd* zi}cHy9U>cRyJ01HLgELKEJslP*IVov=XD)OGE6Y~Hn#_)r~I&ucqZqSh=oRQx= zc15D1Itggi(KSta3Mt@7u^|9HJ*x+Sc$v#}3^P#1OiG1#jUbc~h0G+0u7BPNUJ?o* z@s*5TIBzYhJ7b)ITh0y!?(59@aJ>ODlHT zhlA>y{mlRDz+S0h8H&Z4{#pA zBHgI`M0uTon=3i&1sNO$R>&k*3S|uK}*34#e>1Wu7DP>>;7kdq#x5AEU<44eFjs zljS~@hfDM(#pJ411(>4q98Ps$KQ}Aln_fh8+qFbQBpJ%ZPrLAu-5%vl`j8xrig@8a zB@9hzoBTTXW^*rum%oy+`t$5TiL^RD&Wjug3Yz$-zN2K2D)-^$`oDSKyl(u9GkRn%OkC{My@8S@C$8^OfCIcgEG^# z;`so4D&hiZ_o6kHSsq1}i`lOt^h!u~Op@4*HRO(REFw-GuDosMMSA{4|Im1C(x&OW zK7b5zGyOd@c>eu#l#gd@4@c?vEp$Yr0{US4BdJ#W3;p{*i+8VNGa@6BUfCTG;$|i} z$~?0OP+p+HNj%F)t_%Ru(Q>Q(c4u`n%*-`p>b87xYwb_TOW$+&c8Ei$a10&O_g)P) z<6WKWm-jUzFnA2Sz5@VI%iG&*t&G~UuU&b5|1mP4CW|x;Yivaf=5a=N(qj&*-w#X2 z63s$6l<{)~-pqvLhmP$-PECZ$wPV1C$T#RNqMP@i;EJQbB#}~bFa0mTZ-OB;isxz(HY?nHD%P}gI2T3U%lwXTl`&Z%wkX?%QTi-a*bt4lzY|Xy}|4!-%%z-4} z65&RW|0oT+1C1V^8cNS2*49AWKFW?H!)}@ z=1i0vx6iw_ZJ(@!uK~cF$wx0HdeMhe>1`^u%72>Uf_Fj9>@TlFXv{>|e(e!9EfeoF z>yorX#RLI5Y^Is_gxMRR3wOZ%P~IMKO`EXAV5#XUQIsNUG(K4@sl7Dx?kH*t*w*15khCT-ySnr$f=>Tmt{MBZ6a-IX{21chz40M!H z%|Cp1lLmJ>Cry?X%z`e`HRa;O*-jbuu!4_mM#`W2o?)8<8L03DFsd?wb+_4DTi2-V z6|VFrJuytzE3$gE`1V8jcUb?m=>DCC-Ai&5_{%VHDZ1TbAJkbJa66(~?H0x4DF-Vs z>?lngV;ENjT&YD?&~aMG6C%g&@smklyM8qOB5d#Q6JRDt)QIF?fuG`5#8c$Kf~~`V zkF2f0ewhaDs(B-CQsO2XM26xt$C99>3-2_J-b>#D?>^aJnEdT5_8k|M^W(FUnD6Jf zds_kzg04MS_og=~6#$XGrMr?zK{62*eMTx?+N#EhJ~22d_9^$Vz>1y#t+3zm@Y3$s zF_@E680n&>WiSYcYv<+Jy&R_M_YXb(6Pbe|5u(|}_Yln>x^2?lSA-9k@L^&f&rt`| zsZ*!+qp%4g1)LrTJ_lLp@WXwHVdd1M&Y6k$J(vlL#^I5SSOcc_mBz@#+HIm6rGQyk95lM9fWr2;e2&h1$yufw)M+;; z`p+>=h+tPy$%0eHq8%I2z4`Fr)%ExLXXv9HqEaooDZXNrUfWdsDxr)q;_Md(o*a3# z@HyktbG8Xxe{D@T_|z)+SCX|JU9m}Owy!fCBuBY$2#6HG9!-;mx#LTHAI0b5`H0xynzhYNAu9piKg%!$~^`Fry80yxb`( zVB3j;{WLbBIlA|r*b&)(ILSY+fPr+clw0g}J!Nti{ujtPR73__R ztyxB!tNe_UzSHBn1{}@JFBd+Co6a7?_)U{_y=Mb8*r~40e?%_6KF28r@?_lu`tWUhCD*j+qSg~ETGjH|uA5saeDrn&RV zr}ImY0O#H+2{#sv*|PS1C(!ZHc3d8XE#p~dppig&yj6J`jEntoyr51*Q@CV_W@y0Q-Lw-^jR~`J!>=CsEcv|Z;S+R4QTF(g`d_3# z0VWeQToc@-z@x62SiAkLDRv{~ya0ELw#fs1w&i8`qmyarvT%`Lao~4yGn6bcM{scGBj7fAZzEoz?~7wH@K648s>0s)w8GOqIQU zp=@i-e7~^zxmqfj07KVJ1Sar7HnHp>JjqaHSYUTkYq&g9d07sM0%PX1?U9|$uxETM z`96X3%P4|iH65=zudNjJ^oHn4u0m#LTe71kp@-bpT9u*y@R7{twgk6ZD)9^?Jt;JK ze%@8O+78zgB+qu%OA3e{#>bc(v9hUHii)^2Zd$-mQV>Nrv7%oc<>&PLW4dFB-S?3E ziP10YrYi3)=zpR&GVnzc9vw%L^iMiwc*EBo6YL@KDu)Zwmzd>W?+^hRo&$^rr*|X| zO?GSQDo*zz5n|tkU*80V0W~4Se?cQgmACQ3c)tRVDkFHyzJQZ_E!F3vC@2n!i|y-b z&!ydqWb;1Pn*>#HC*WUl+0ou4BmhYhW-nC@QA3MUQxmvOc+88!-qCY$N-cB16+q5^ zUXWBrgDbdpor)i7d}LPyq+R<=oDO`7gxsy`U}H^~wf!ii&ZTn)h%K}Bduuk2VwxzA z(fFxX&;wqDLdINb_tUO*yZ?fp9^<$4!{8IkwV0(Lfjn?tiUr)w;*-jlaXHqQ9$y;4 zE_$qcNRmNY_xiobI}aK0L!TbUn~!4-3$D}V^=*z%>Rg@cG++5yQh-B~56nQY;#HWJ z#+ch&dqjV@$L^AUOaYwtP2~e5`u*_-?$VI-&Qv#(m7y7|X`L6KC3^t)zrrKdX<2pc z&H?U3O{{(R%a?NBF+emAXAhasH~%qNuR)DfmPmcggS4bBZ?UdU^(bgEBE_e=2V15G@N^rj<(db^q-2jnBHbbp0_4uQgz~}JfC;wi6I^eFOkt9zu+-**G#-L$42mMFw6(tuiIsKIp z3e%=3`<)g02)ZO+C;^qeDXz1^3Y2sf2!Yg8+PJYTo$sE$sW0Ixnt33mWq&HSd+^M4AsUfim^5 zlb-7<{azfFzn9iQ&3fq=$F)y}1o`~vM+pOCMj3I;GmT%D=k+(~n^ezAj(4#?lkzi` z$eWeOX|p~NHJD+_6YVU1<=3c?*|n+%;1@NX)KyGc;yW35^weqX=N`Q0)L8?pOeWNl zH_hiwiJMkE(F6iPT>3;j8;vivE|b18TwM|8Yv$om9HeKpZIukun7h!+m=+%8 z3wVG8tL^5OmpS>!azipk{cBTQy%U&M0SQlHzB@5udI~vhFVO9h4(wR&puX{S7KH>D z7G3R7jJ`OnsQLs^4plIKj9kSv%`L4s>cj= zzwO~8Cs{_I$yQ}goOBX8E0%sHy-MR3Wxmm7{W9xK6f?J&hHGKA%BG!ahzXlFslQGT zNTDA-27ZBGs5$O(at|N>{j`tF1k*aiT2S_rb^O6MGvivj&BkH!P>N=x|5!uG_?hB1 z3ajk#<5PSrH(3NuMvHx%i{bw98*1NSRTTN<&=KtFci@;U@2btUqCg1M zdXEZFWbLiSLYn2Nf`sUp%Z8SU`$z?uS7i>rEVdR(XXD^MMWImPhjNZod)>$}#SNCx zvT(cekxpFMgUK~*N!Fjf2ye@XiDVB!M^<(r-8XtdDlCuuH3Zx#CvS^oWWC3~9{YtwaD~jRaj~mo zjWn6UeOC*pJaE&3f*+r#hWtuOSyd*n3xD{V2)tZ6N<4~e*4fnD+(krFi}#`k1Ll4b z!jt_Cg-L$jf?ecnu~(F7NCgAfy9cUzOO7%6N29Nu@EFW5 zj>5_Qd(}i=V(rmr?mH1?v?_R^Cc8h5LHuBCm<1o4-;Bjc)L3q8PwVzyI^!d>WT0UH zZfXIqNZH5o9rFtC3m*WP4jWX+09>VS@43v1KuOgP0!jzZit$THOFscGNi^ws$JFq5 zdK4kIG54ST%)$TTBZY+RpJCg1%NRS2a22yGcBI$0(Bwpzt(L{m^v3+4A_qUD(f9U; zjs};eWkc*f1v*_wNt~FTo(ZIY$xUS-O`oNLA()=96`lW}5BR(w&x1`4r#0A~cRbcX z;VJBo58w(;?ZZTdSzmUZ`CynVjezec{3Q`5WH`Wc9O>SZ9r(tn5X7wTe<5aO?uZv) zF8K5$^J0xU4IUf~SA$`%&v&oS+@KhvNWQoPJ+fb3E0qbjeshsF*d`ACG@(NgB<9@q zVVbbvB17R)XDrMsY|YMOO7BE_xNw^H=sa7gHAIo!6b!O9uxq8#`(MAr%A6&}LfLTd zxumf0<7#8RCD1_yS7fZ7V!{3?QqsZ_<1yzIde- zJMhmnsmTBzEAU3G{Q4Ufk|Oh*bHS`7S@rzLo%I8}pmyf7q2DJa;Tjgnssgny0bzD- zc+M$f({f`1z!ZrNXXXJW{OyRnaQut7>sj-7K1fmhQw88M;~BU1PWs+3eTTe9@NJJA z==_lSU|zpMeFAW5z_ZYQwo^vnOY<8Y1hI-c?p!VOoe@P)ZgWODNAC7U4ZXZ`vhAE| zsw*&G`7e}Zb)`jpv_>q#IecpT!#yy8atU<@ux0X+<3vmH@}O^f(Cgog6^ObIS`FY; z`$j$s`tcmsU1uK_+=e26$T4Z-!wu&a6fJqt=Mt~X84H&WRf+oc9)F%nsNdMAc>`N4 zuW;$CG5w`KrESi~claB<*D)vn(9$PdFy?8iH`wZ3`#ztCyw*ol>kp0=hV@*hwL3SM zW+3mDW5)kUX>ehXLP6WR)ca*n>jmUGiAQS8S^a)>aloIJ%++@q1`P?#HGY9xRZc&d z;qU%%CaIp+i?qlo1vzc!OIj%%WX202L^gRJ6~_EDa}VwR{E@NU z^Dk-fFJk<%FBG=C=7Z6R=rph-^8~@b>gww3xflFwY+CB;4J?ze$6J0twnEgyB9TK;o8wC|G9n+P5n;=ZYat&paC~OeL678-2Mecs6P6zIi4x;Kz;!T z>VpK$cA7f8XvsM>Oqk`Y_4tktWBwRs5N53G_8RVYVJioQOZ6iC#O3RNs4cCCfP~dHxm~vaiEb_ zZWAd`PY7{=PnZsct#Oks{H?>=hKo@Z>_Bb?*az|mMZOWR0)6$Jt_T}T^^J~%(Q$4Y z2|g2vQCjl0=XNt~y{U!o)d%E5`+MI?ra7`O6DswyFTJ?X{V1J(n3Iljee-HEpTJ?? zzUQmn;avv>l>tAmzvrVUZlF6F-&gPQ_F?n?l^w( z>g@>jS1N!i5={uEp)Ju<}%mS9?kHndn&wezmg z3O{#HaQ(#R)*f*Zi%bU>8?7%+-+Y6l9Y*{dEhcx~2SsqBwCriQL6$nxa>LmiM3{7v zEfP8H7NOc@u^uUZ(t554+n_1$`|xgx-_Qr}1+w%gii&BEA}Dl)8N8u1y>yly0&`2e z&o1=KGeb*0;dv{~cKkZI~(FP64V~(nk?IROP~G-X6qQcXr`lj4(O?m5Z`3sXZC_WU7IVmtFe?5^?p8#E}1UHvEFL%;&w ztPU?VX)zfINh7b*p3kWklX{tWZ3(egI=d8=7Ui1i>cHC*yyPj#x z!=i(eC=Iz@&{b!*f zW5TygMe@XLs(`hMIkOFIwydkk;o!B_WIVUBRPZHhqs}s@;#ZMf??~35|MKEb#?5 z-SC)75Dn~2&b);q4EQ;(O1^@nlt>X4OcR41G6=qr3$%k6)yoZvIWDpHyB~|?^;LN_ zkk1m#eFBXieYui3F2+#ZTdAuBq6@bp$bt|4v ztr2^)UD+7DnI}bbhw0|jXm~`L+sci^F=#kOW*@T!zjGGe13yEN<+w`)jG02|WCdxacU(hNS@y{gHB>TV4Th-ZOwBZmt$UyM|BG3SOPOl%~bZ zr#O05$?WIIEq=F3zqt#1Zp?yePYb>;XEDFiC^(+ir=r^om{TR6GA|v4In8l_EB$6f zlHLoCp-S(VniI3L{trGqe}i;&u=YaE@CF^Tz)`~+U*uUk@&YoU#i~gH1gnSUt~(z& z^)tXTld^ndvs9+Zk<8lTE0^Uif0631;&ieqySO`a@+r(;XTa$R9nhpg3Webs*%W_= zZ(>=e!~KB*uScKP7qYPfor@x{gs(0Rfo;BJS7cjmZd1GE_n-&tQX8Y&ZkaR)l zy{R!O{HdOpoXuP6xWzS(qz98+Jj(9*x?f)bMp*Ux{`ubmiHAJi;^9W5Bg{C#$6mx`CDfX!xDu5BNX-jN2#bTA4FzAl=@WKK{z2spjwrgj|P?AlWt0`#_~~(Xwre^{1Cbkqtdl^L-PBZH1z5j zbYY0ACsPHP((#_u+oE&SIK2`+?tgP$mm#lVoF6s8C$r^mOpd9;FH!?LC$A2#!WHt3 zEh^i?+T6yxP(v^Xxj4iiJ@0@;%cqvtBSfvsC=&hP??v9Am1*;P_rLH9)n$q|aQqUm zd_M!_{2mtn&-=YEg@9F48#m$q%1zK_cn5Kvg*^ zn80Ny2TXr7#EVU>mwrcHGu2(e=67)X2x1&8q8lm!}4i)EY7>l!rW#*G_UMt5~ior3c9mFkh9>Y%Qr{e-DmJ*^EQd??D>VJ7kHQ|VP-)7kmi4BkXBDa6ao^g<|*tX0J1CY(`V#$UF8 z!S=MMw{VwEqM}!k-HU!judkGu@xJqKqV6iz7FpND#{li)Qb{D(-5J~PQ4@F-X!$oU z5BLyl+^i&eip?L%o^XXlX2tgmRmr}|-X(EiWgbKHbXZ=!7HvS+w`hjsobCZT~0DU-70e%Xl^J~`H4b&=}+N*@r<`po?W~o37JoyN*^9~4HiwE z?bdQ{BOu6nGj{d=U)c)4S=Szilyc=H1&VU9LjQ&S9nxOld3NHQ9IkR!>CtC+5%nI5j(w;D5K!$Tm` z^F)bAZUJdPXrm)k19$oTmC+@mm1f`2oW17i1y#Ckw(NWIFQ*uoghHzSZT8-!Z6iLIg_4Yx0;FpJ*W*bWb1radc5Egko?=kMnU8-s+&xWJ^ZA=@usJ>+sUf zc>>>@2{q29`{$GZSPavl0lR9jWwRqFcRDNqjI)@PW4jv=)LIyJ8sgn!1*m6wt_qCdGdl1jPHr{3G<U9lRp~@%nz}EX3)UQ` z6WpLX!k1%t#KyL*igR99p#xTxubQWVpgHLBV%wwNF&=(Ix#q>+={2&Twq*Ta5BF;N zuJy-}M&t(4k`5iHFsXd8ID+1@gmI0IL!{N#4R8mU?6ThJVU1@J3nwghHhvi*J z>Tt!zFcUZ=y`+ISV_sKRF~C$_ zHy}Tn@ET&O}~iR5@te z^AtfE|BUhGR-RJGjAfi+^TWk!q%c>$^!>|-+f8vQ*ktbQIR==4jvzsq_?E@tCrMtu z@9VE8A>A@}19re#P#}yxpG9A6DJex2 zI+E*`D|EcLq+}?+?RVYbepOn8|CJW03AKRNu)0+-IvV{(v}C|6M5mLq(`4=Y{?$uH z&|d%Ica>QtjICl^48dNv)7R0VqPW2+(EP4StwN?6?4k)Q!Zg??E`WDUxJF+lRZrsZ z=(4Xgtsz1=&c#A$fY*!>KwY-8+tl)Mos;+;xB#PQs8CQ)1OkUVa!UNh5zSs3!Ui92 zZ}$;j|FU=lB7xcj9uy&klBJW!8mDEZ{9mTfwoq;ZBK+yk>nJT zW2%SBDtSp0wo}B)z56@}Pyhd-rh0k+EVV}pQ`aA45M+vCRIdK3ZaB`+T%fEb2sf>h zO;|)4yT^3s$U!;*mK`><6n!>Uq|H6SU0ENImZS5g)4l2OL4L*0isb?p3XB-N-)zBe zfyZ{1j(zlxg2SRT64`p5snJ#g&uq*$OPpe_ublts)8r#pMnFJ=dnY+0T_x1&EV4o! zXO3phk3JW($9Zvgc3c?Fl5`{ZI@yRi7dj$GhNpx-ovx?sLHHPCanTGx=7TaKegOUZ z0m6rSeVY=sc^tM4hkvD2|5gVwpI`SW>4IMITSU?I5@;=Vf4)fi@TexuAn(y?_ff5k zT1#~)qGFKvO7mT6e0@_Xb!!ntysgzJ_(44^2`QmWSKj0SAPnzi zuu3&5aU_yGS?>Y;(8J3b$Wb4D>T_}lR1q2p5hE1c-|o{EK+GyPL6J;zuB?wbBJu%~ z02iTSr;354Ev$A6lTSn`aKd`&nVFf025WCu47lGidFEdlOa9ZOoIkDgbzzaUY4}Ia z#{2lbG7mrS>HVdMo9Tu8?JKE7nBwA+!2^Z8ls*+#Dq#Hs&9TeO%4q3sAsyEx<4dnS z3Pr^gi(iNytyn(YINQiegpHa0X0&4JH&trD69P;+L~LUHDQ<)Tp+rzFR@BWz&W#9` zeKaU8^3qrenu0!V{)E~OGi7znn5TjLt^`=h)+tV;E}((Mz7{xm3x-Y`=BQUUE)bNn zaU_A_^f-BWliw1y>kAe9ChoI_#N;#%%C2ba@{aR~|8~WVmGiUnK3`tjy_Ms=7TP(p zdTYD+qV2=CuVSL0AuWAB`Iwppo8|Tlkjet?qnh&9VbLkdB*fqNh&>?$)dj<85V?rr z`d-K&_yifw{M8QvZNl*&CO}% zp;yQ2`R2iQQ412@&<01&T8k&1Uz}!}uZu!@1$q3-H)|#ZaEFtIradm5rw9Z-MPQ4v zzFYy2Uf)meQAbmsK79(am&iqUR@-y+bO9)&&;;#&V%ZX2>RTmA56oX7c-iuxCy2lU%pPyWWA(v=zagkfOC^R1U z+F_l-JI6rT`3`WMN_7d}1p_(_ZDQb-^30nMp2L2C04rTTvYEpnbL}{c_83DXw_y`L zFBA!|dJB#@m;DTZ4ca{(npS5-fDwpXrz8fB>CQS2K)eRlb_DpA4g=&UGV}_9WG#cK z7sRD$=K~@^IY6hnLl>Hc<*z+MfVH;gw*jRvxy!q%OWZjWvD#sWtIYIAla2S6lLn3S z71SswC`uw>ywUK>V@hlf8W35xgx9AFK2?wlkBoC2o_gv-++}~|2GZMovCP!BcTnKWWwG?JM%wD?WYaB|8s@mB zK>=qNK}KE33_QZOctncE;`0i~1)4?Y9H#~Yr0i>2Q}s88MW)0kOA6|*z1^RwTN%#X zG!S1W;Wij9sj%2>(kJsfK#mmkR~i693R zL(!$~M0k$&Njb0chho&C%>PoT3W3*RTOY50(i4@dn7|P9E|zxl`}Cv?#rN6vq&K-h z;U_q0YHD&TZ{;a8FMd)(ZkTuNN~Q1JhSGE${ojKA99iqmUbCfCkcCv>)yU)js0bM+ z+yBgqA_1w6Tn(XV%_-+v59UrCFqPX)h2P$p#VWgk1dTOV_~?Z?gN@$nPsLYv&nlHE@la+7Y>_xH6ws=bBKW0Vn<0_wQP^-_ z2KM&%Y%0XBpeXUwdS?Z;KnZc1AxK4n^3fzIMi&%Ur@a29B7m0*m@ZHmZEi5t_yPTd zR^9QnhT7l+j+<*L6=t;@plrz8-zZheOtOIPWEWUUUGQeqc}dnJehnQk-lS|KELS>< zYVZ)uc_*nb)Ip2^I0J$U@Pp-Z{lIGheE-Cor^h<0xHMZ674v0%X17s`*eFunZ{dVav<0 zzv`>uVWQF96OP9pFm&J9{5CemB)qQJQ(P(ER#rD)ahjm~NFkX3wLp#C&Gg03zqcjMioJO zY1xp1w3noey8IuYAnkpFZ>l zDkARF8tAx`ulgTnFfe5!8OSF`Tt|j<@+Opj%LP!!X7wPRA$g`>8Gkz)W~B9L*ZbSn zjGbM`D=XtqB`Y;7Qs-5FR(7ykdte`@p6gekERIY7(}s3gdQ%BhIH}g;al$G*$Fhk% zm0iE5lYZ&xeIWZ#OOf^xisjsG!t&K4$i{`R_tK#wYad0FU8m(ta+m0Q{RT49wpB)D zbVo>FAZ5k{EoZAIO}-gBY=cym@f-?SVR7fppL#ns?7ENcyu5IM5+#}E=@Tn+$>98; zAj^E z(|6VypU@NUfJZqz(<6yJq3LHx;c(-#VT~fvAzIb^=09VX29vh>zO(0WT9!_vCg9v z=_gSQHV9$($-sybv-mECO(c^r80;c5CZP;LTN^10954fx64_SOpM!ulfDmyv48A7C zNW$I=;CxZ$QJgCz;UP~rYZlw8{ujHvURx4-+WxS#bDX1t%`x)|tr72TC-V|mLY@o~ z8J-h;@alyzC=Ya7uil(vb$!CCugf3IRyvWur^%fk9wGR71b(g~SvHPO<+_U1^#pPE}7M?*d>I#}wNeGDLR^QoQ z9@Z#1i(&-X&N*<%M5g{jSb>z4m6}~Vjj&wqkrx0bm!vlt**P-rW_5**IDlf{Db2r2 zE5hx8Vn`f(5oq5ea1>Fq3mPdTu|u zI%~bp4voGP{gzf-roubA-*dKDDBB7EV)zB* zTDlaorYpw6j9q6*dCdI$SC>jzMNs_xOLonlfdVpxoJ7ifiU5d7ckTl{aB_)Wgqm@` zTK4iW#CVx=?;Zx0QnAIK7m7~7N9NtEx;fAsMtoIS%RB(oVvC4Uf%?`ri`f@kLAEaJ zttSET{SK?!|8K^{D`+?A;MXyq<#t%sT%L!M63$im_eTEd6|BAY0321R)`5#Wm1r63 zmyEzs{j7oXU0#^k_C1Z^^vfIf7kJ3<02;B38d{7FdXeE+#KP;w7d@vZvdA&hUuJ%P zeLPV9A?{D}MA9fDE;c@{@b}R7(lT?y>n6umvSUv7L+uSK2XOS}(;bAG(AZ9PKJul2 zOg1>qzbNK33CE@&$!u*gS2~BI`10}`W>?W&}!8=_zG3nZ@IqJiJ2J@N0(Y}=+>p%`in_bvN2pqdJ zDC2<8G(6QF7>cj5q>)n}tY@^7c(MhtS0YrZ$HyqLXFgTOrSvTG9-Vrd&yE+dDO~x} zp#Zy(_^E6m8f@lCm$4cvXh7|9RCmFXy5dMq3lJv>ZfU%TFIO%Y^wNmf%j^8oL?k<2 zk4-ue)9ac@L*HGk$3CvIv_L!8GVd&w#wQwT{M&zJ@!4}?K$=~7XAc1Cfq%H8fz@xE zf9yOH?hk_HIHc1heox!rl3Ma8m|Pz7@GKhM3Q{76WdA`ykBIqeOF1RhH)I;HG+C}3h&r>1E?(#-Ji z@^;~KgoT9g&hX|-7xu2oN>z4TR?1aQ-gn`_edAhB1xS}sV8gpxQo_6= zCuLW<|4(D=Nc98ez-33w9NS4J$AB6pbsvh$OgX47#akgYER40=x*H7}K`?=`RsbWD za>b$YGS?Y^&PeUQu-2t-z!vN0&p6rLTm@p1Wpv`n)m6=h*FQWXMC?R|ugSy5t3EV^ z4x2|{i(8TtxgVU|-a>%Eoq3-6K9B#=kgD0@4mP?<7vwhj6LPUr`w zEhsVR`1h=%&(%G?-s!!t`6~Hz!sVBM{u!e`pQo;gx8-`Fs=-EVKw|g zZw7<)PhgjRCo?2u(YCCYb)9|C>{ z$y5yB@vyijxg&}giTQhgCxtaP*|gum9f&}2oON-9R(YwX2P#{? zf02rLcWIZQ+oo05ijUC^A~D00w|dJR`|fURO}=4<3!@4SBv=|ub6 z>!Lxt!bDT*Yxd^8h?0uZ%|;o_UYIAt6n<+Fiq02tmtVf}1<&k5yUnc8EcEEvJN-p% zQ@hNJ)~)h-e52Gjx-;m9-xNmcueKP=XqPsmesMJbB|7t0L0?KuwlMLKoiiL7htGBOj*v$8a!|p3zI*mTb$}uJl z?Wn%{iosqicSHDUEFeJe`Y}4QkY}ze{N*hrKw{KhM=Fee7>Vx-wKwMl|Fk}OL$CxE zO$2Vp91(d=Adq=*9EVm^oRQ%7Tn1eo^_0w(oGEgWCb$rFlvfpvzg~;WS-po}L9hsG z0}G7*{mc*q6*3<{Y!YtMB@JH3Wv_3s0WDUqVl>__jBadOf z1HfTJ%{0&^lPXJ0pm0ZUrB!{z=LFshxb6PPqh=4*5qG7sx6!&$+KEvpm0N$$WFkS?mSQ&i#_)=a1*vWy%1=eccjbN0gGw@>?JKP&$F$_w6^AXC`0~A zbrsjHc!bdkquH&B)+G{5=gdis&EM17EtL0{epXP?eXxfXpRDm>ldp@(tu&U+891*H zu0Ws|cLEf~!vTQn^ECnFB*=#>i{6Ng=9`pLJOTE{7fuSKhIe4&nxh54ussv85j2{0 zwG(koHG)vGlw}Y?ubFXKN5}tEg~{6q%rg1UmWKy*@T0lPH4)9vHYTzXNc|2&eNIe7OwR;@=jn$&Ui% z2eOI=^O_@?A7SAJkN=}AIHQ%uE^Lr*+3>c_TOMuLIIg#g)JZokD?HOasoEiKznm zGN%;GQeXxm3&Q8F%|wlTEQcZ&-mAQVkpA0arxe54@wb2<1_M}X%i>~@OtJ3cOZOfb zHkjXW${#4q?yfc4y;3O>YV4cq?0V(_r&`zD{Wr$DJyC09gE{v4&*HfB#zBHD>Ok`H zYAUa;l)xvj`1z$`K&7wtu~6-(ZtVG>hFn(RzbEOClLr8}QHBtI_p+B6UuF!bl%?d& zYph#gX>?xzAp@PVtFSy~`VpdMz6PB90b-E#6#E0&!jv=JkT6uBS;ki{52#Y&cAJ z&EOBa{H;-xWUH?uvu>fM%)dl_mmap}t8Zaol%*aCO=K!~Tb9HL1myQXdP@s*BqHn2 z(^DYE{4i>gU4Cyc%#QyYA7GtZ^ZidaWn0-)X<{WYipL=Bnc*PCVAGo#GD9+47KDkx zHYq<1lx7cDnhdCwLCFcfEMh6{{ljNLoWs_FZ{nnoBvWC?CMn&fM(p){P?`+(6M!bG z0i>Ml(^SY0-TwKZE-$D-H68(6JqRdGAA#V^TCBc|)Fr}IugI3WQ8NZwjJOcdy&p*- zc#z#>e5YF1nnF9i0S)pDC0*FGo*4*4_5|Tt2@??5P!#3%m?Q%p*S7C273Rl_c~a{K zQ%~uk6{?r=fJxq@>-8;X+O8Y}|Dh9+EyC>Sfx)*OQDDejhe0Y~`Io77*%Sep@=@{q z)&-x-F^ZXA9`Qh{*XP}|@&EAK=OAnku>*VQ%(lT1;BUUN%0cEhfOeCWud-1B;r6SU z9@JLkQFxA-DrM4@>>rK(f=O2n83H1Z+WjR4N#Bil*S`Oy1knT|5A0O?F0O_`IdTt) z5K1k18MNLnPgeUl`!_c9%_d?7->kTt|ra48o=w z&wnk~Tone(N6OH=Cw{g{b0Tf~63@J@ug)U`ET}zK+{?i#?=RHZ*)4`@2#23kNzHp` z$`wzX$*Izugk3DAU$nN<5)3MeCE8Gv88YN0p2l~)9WUgH?3 zu#pU`5^!LU=NuD6qs0Yet#5oJ?S1{4YU&8+)=dk9Q0at_kOFW>285+ll!XD%vQ>L% zk9M1FgDzeH;n-lIq<*M%9=;r_V!(kuD|L(Ynk_XvRh~UGEw~?xB@;)DB0c3I)(CnP zM&;Un$VB7jO1)e;?$m>I{M9551sRW+_PHpX3eDbD2#_59(x2@DtE4f+fCeA!h>QU} zhwJn7&PO1%IwM=ztCSG<2N5Fe8G;~p7G(5t{q*l2s#EPLoYcKluNTYx~_v*^ahb74mNlx4a7iFc6_Kb}oOC~Fejc< zZ%xiKKqy;$i3Axabp$|a_j&TJ(PJnYgUq|?fKx2}z1p5nM^CTIGO;}yl3!!_^hNp2 zxD9H~p@)<=h_TGf+3b}Ox%3&v+;s)q`V&_X2~2{2%6f@S`+nCTAxM`xqm2Y1rwF8G zUymcS9DP()UTYvT!R3Q};wCMcB%r|Lxnk%cw!rr!SliwQXm0=xs8?^@%H3&AF83g$ zosh||A%`6_LHq2u)e!g{HKd?)x;+0TS6)ZU#!C2#1~uEg^F;ec*F?*UfR)5(tH!n} zqazX75gJ!`{egbfk|TDZ?f3h=i2SnDl>B`CQ#aSbc7n)t3$>U8AV=(tT)p*lphU{a z*!{KKS*QUx?ar@|{Jc;rgsHJ)R19S>B(a+ONje{5E?d4;L5Hgtek{VXcHm}D`@#Ox z?HDK}S{%G|&qbnlUIW@owjlt9{y*p)D#=aVQk_h#j@_OA-QF%0{W@iEwk2 zIx9sm0X_stEAL)O69E;-^=`72$uf=M9s$0p!CQj>=Ph{u0NNQ?=KY-H4M^h|CQ5=w**`b7%Y@~VS6Y%JY=eW$q z>R>0HqviEnc-Q;eSL2+Z$`|^T6$Itxy7Xm$xGLsHQ!14<4;J8;vn0Gyj^fN=8LfO8 zI%-s^CmA{rz5~T5sI-hq^z5L^MUr!XV)vi8X20AK18~IPCpBZ^BUi{*B+q!}z>AyQ z1?In+&=gee2}ug*VMU?$v!AEz1xCbg45}b@W3$>zKp44>zM4mkIuIcmEZ-lW)L127 z%1flh6t0=_{u&QR68!83y?i(#`w1oDM8L}6XNbJmrNjMQ6*Dyq$$}&kash-^g8a9G zeGqm4817slqgdi$;f2$(|B5^NC}^AGkl9j=+8U`eyDAs3&J7!gE!%Lh_LZe~)$;P3 z?8T~4G=j($5VY+%0>ryNPVNGf@;;B5dh1VucQ%UVrp@=c-#^okNT!sO-MUm;3n=Dw z!Q|(MJSW5JPQ0{34yUpd()H%0dsW9@akPws+Q6IzM9|oOKs<&{MSg?lNc|ECvMGxv zHQ^S=X1^@06B!0JvEo2gcUtcDYLDrM%%1Si3t~K>Be9H(@4YvjD?XTWT21fB8j`Yh z8-w=YVDv`CSiK6hT9M^g1Y`jj6JdnSjTJ;vSk?r%xJYqX>Q7|VazYjP14&7Q;yyeQ zfvWNHp653ZoO^T4mcm83Y6SPL=pC=QZU8s#im1gZw7NU7*|XtqupP=r)z=%%usXF6 zkqpx3N4=W8zo8lY^BIIA|Aft`A<0s^Guv%u_Z9Y$nCf8~JHv|eYSa;3T1Zem(5H*o zznMG)ICN!{QzZjVt`8bb1THud%83G#(q1u~Q1;8pOSrbeh|@qxz5(dzJu%#DRPZ}M zE=F(~4kz%3pxgm$pn8gy06(R*Z~#4k+kB!gApp4E-#+fM9#V!+Vv!&YL#WXGA_>bI z;13$_jOhAdC8ZXK1r2{Szo&EW{@ z`PUrIVA!3=?y|K!&NwmukJ;bYIorAF3nHJHxd;gr*{=H((~)Pd5n>~LY5vxc!3b=6 zj@PAw5h>*3xfMhcE$Ky*Ou7!QW+JCG;fW$|xH=maxD68U6(7WxbQ00OC2}aZhMq!} z>zFyy3=u0T1KvaNRCIkdK|Gi~FJC+bt&F_`8wte4x)EIRqC@Qcry%F&(~moSDoZT@ z=rC!FIQ3`!yy1V84WBlqYCd7RyM1=(9ik^EzXniJz*M-N`?o}OY&Velf_WtbIldP^Rfmb-rfQ3&g9{GVrp zzDplCcI~?&0LT1?V~6ttYy;>;%|OEl-3@C36VfPkf#o8}>A(040iMn0p;-j|CIL1M z`VM;Ny{!PpE6_@7-S{^PKqZ3zEK;b7#y~6|Au-w8ou6O(Ulc#iOP!klj{Gy;ffzBg zUgv>pKXfD}mCyO0Z4cRVmtG5O1^TYqA;SDc5i-JF5}e$P1r$4Q=jqO^f!l>(IX{e< zK=)9gphl|!@wyNgEH2QKmxHcoaBF1}So&fn5SIr0{PKm91s21YyHYXX}(B^u$ z_4brABgIF1o@5*z zWw$XfG)>lHiYse|Ng`tjCA*s2h8NuNoqQF{QKXIc#K%c7!WWMyYfZW(FNaD5Pxuo5 zdYuc(`O54L-Fy(retDCv-3h3}UA^x{Pi^KENg*980co%sKFzuOpo9K>G`eeD22Ycu zarY3cwti}O?z`^iAFI741o#cumYE2lZm>prLnJ&2T#&~wD=^w#=T985Ck$=t?CQ!o z(5O4>8Zf^(W>X3piu9A=muZZVt^yc^|2Gxjb({p{s4opw=SGS%f^+ufc@n@}h{JXa zRP6Sm3}pt0n~MuZY=Hc{x?1Qs$U`7#ksQ28K%_X@VUd5tbF>Hh&l77-xB1C`9&Q2j z4Z5!2)nafx;*_rXxu8rD0D1g-BF6e+mSV76&-tmGr#>EI*S#Z|tFnb&_d8CEBTRMOg>*y;SxIPZSpniY$7IWf2kSdnx8(+9 zT)By{setL1{uk31;M$Q!H2tc?9F!#U7W<%PAA%engx1*j7Q84m3Ki#5tm#0S?5P@a1p`sj-YfNMvUi;UG~i2JMp;B2PowCo+`D#4tE4 zcy>fGenjZ}`h8;16_O4lLiTS?v;>@O4z$<#Qc3%`&+Hj7M!4xb#MF)T29FS6Bbac# z5cl@3W2qL@u}JjNPbdx_d7qLFHTF&s?3}5Y{yzQ7B9RC(p@y^d@*ra_QOA)6RsxOd zKn+Jk^|HNGwgkUEZ5xuPJ>c`WfdP7R! z=!MH&@%Lw$ArQEMokm$}c(@KF3n}sSsHeV*Slx7%Q>j4$QJ#5?976%dyeP=SyF*8s z7)v86qeXJ^gFP5p$r^E_e@{^CXHK$UZndc#*?Pb9%B!S{$tDj%VkNGbg=5$S-RdM9O>}%+;`*)QO?e-_T&^79hR(e%wjX zi8AJy`>?b`J`sODKm&)zqvN5nayjtF*&`58njgHy9HUzN#}vtH0i=nV^sgJp@@6E0 zYo8&L??aiD|aM?IeRC|67oD z(jmG+O%0?p%&4&{Cr=V3*^s@lRsb8S0ray}C_e+R5VM5=MdDEP5$aH{Pqz!n&clEW z1%a(MIRFBGiN*b`HVL7Kr9eTWC=x3KeP)0mCsaCB>eg z94662Yz!!H4s-Di#hzBjkq;>@ewavU=kG2tDqpX&4RGwx`>gM9Wv*U(eon?UO0PYS6X81 zQ`nZ{-!3RarlH>P7gfd%K73`COwvZyWiChaL>MYFk+1h|)hV3-l8{hfw} znuxh>{0aLfq3VZ%{XBXTc=%-e>|KTin_D}@SN+^o35n_dfRe3P`lJoy?dXCU2|{o| z91d1BLkPjGd{^Cqlshgp(f*JpJR^O{?e>^2j6di-;c@A~H+UeJ!v^nwUhQ2(vRq2jrV6Z7z- zF>gEZr`KF_v%nZb9hxuq{5n2~MU9>{37WK1G5_)y|ELLxyK{c$=9T@PT~6sW`=W4D z+t83!;YSDkwWu{lvPpo9ML|qQ4CP`?^a((1PlDENNITrzrP_wMS8`PSA$U_=oY;25u{3KAu!BV&6{6h@A?PkZorFfB^>h(LNK5?eyM+#j%L73P zeSFa_gzm3QHKc}+gOu&IHZ$&gHS?=Shu$ZjN$J_h8w@-%X5jR zaM-;q{pBy#x-A0mH~ZS!>0|W*7Tm3Zp$yHJL1T{lYo3Qfx-|2GCd>U_ziya6xJEcX zKM{3xbCtn58EATLuSb?G4iNW2Ra;-#QqL^!Da7+m8xM1<0HQHpfQhEM&O|_~J@~J~ z@@=5`P~|=-C^p<2zP!%l-OQUMT)y^*=sQDDh#lgUXwoJGn2>LkAMhd91#4|ro=d2V z5iLYC9-~SP5R&P4cnBedkgPm!joypIp=lP>)1ZF^WZ4(;!cCwVcAZaz%gFTn!5Ar$ z%>W)xBvx{#BF2N?fC7OAA>F#__VptJyz~%AAPqRzn0JlgN@|$KZy^UmzQ(lDdy|(xf$Ur%Bxr>Sz(@(2hQJ@UTUJ{N=3>Azv zeRzuA{{BcVEz(2!PP3YOjuvXN!|=2^$G!zQ_~;0uzTpf;=MluNqU@9S9-ND}q%|}& zjLgkhVj_$o?YR%{>-%KubE^Ij0Fcw!fB?iJ7QTKSGv~QG)COwzLp2|EZ(Drn)VcLZ zQPq%`6Vb-fV80IJo_#}O&|ywUh)?;wS#*{N^Ramn5}UydbnJjEPv#bz%T?o8P-6ye zENg1eoU+U4AwJCM9xUSXTX~mG!yyCI>U=TkazbLR+~ABt&;p4(5@GN*sr_Jbef62h z{{Be=xZVl9D$;)3fs6kJFnu5g`G`r}mtR5bK2j`NQvMZN($Z%e z6o@nMlj2R^_NEJ>=Y(I>>4Ib+kFfkCoV61gPsqi46O9p!^|!GLP7v{KlfW#;G)4Ko!c$*QV#q& zef{RK%gt=09KoLr^{jemu&XVX3F^Jid%e;oJc(k|_F;Aq`tX}kt@PQ5fRRAk36MN} zHS&Z|E{Oh2<<%=BA;g~$w%33l4fE-)BvyUU#=4IK=mT~d&y58!Dog?*fQEd!f2r3E zt7$-uQY0RwU^iij+^oEpn)=e`l%R{^!7Y2QPJNE$!Y5Bt<(aSDc2#OR!yf zwiA-S1F>EE@IO?;#B0c#I(*SlMB;jNEb6Zz_HTO(ss-WJmT*%j>#MKX+bhsz@7pK| zAodY3rf49-y-p^#t8*(~D|NA%aN z98!&#(1$s7Ze6NW7)FL6cW?zhE$N+%j*l+TXy50TM@^SpXWCF16kOwva7<37-FTx! zfn)2B28uz@ z!lM7jzgQll^3t8T&9{_i?f{YjYSvW2|EgJc*o8d}f%)zdMhgfC6j-D^GXUrQnQO-W zQf&u)W+USo)1hh534@Wi^DT(VwdVM~J8}v{!P5NMolj=N)FnbYx&HbUw|Ij|U{oCaP3Bc@>=w+)nfMHVl zD#!dhEYamK2nd=+hM=PXY+Q%j&*$f%9YJ(1i*x|{F!-n?FrOt0H6}oG3Y2eiPWuDB zFx8K+;N8MYZNI<&JlZ=jPzvnBz1iN&-HAKw-8B5iF^Dbwv$)4aXjsD}Acw#wuCBm0 z`D6;R_|xC808+K(n!wS!kg895qUXxh=B<^okoJ9FErN1(Ow!V6{b&7pM2L%Ej>;BV zJpSa_H}HwX)_m@%Kp5?A)Z1cg1+}qtQ+Ja1>_fI4A@}VVk>wNW} zd@q(x%g{8$v-~$6`VI~BhD6}bEB@cQMgV@R@r;6Z&HnM7#W=PDtkT~Gl$E1&AISdY z!S)5B476Kh$UUJOpM%phWWUyz$sF9BrKltnkcx?QIj-$DF;cY9Gt}r?7H5C#r~~fS%|WkR0XbgRr*OoAlowC*2yD&V$|fwI?4&XN@J4UveiTQ^ zMSxaej<#M5n6xWDNf2X33!nNx5fiIW4Vd^RBK(Q0AJI*PFNyi$^KA*rd9?3>&^y7+ z?)ANgu*89ECnb3l7a+GBb7j>C%_;>(_{T7{>JPA<~6EX5AY=N5<(w`P8JthTk9tAzvZN3fh6iI)ut^FdFmoMiG>+Ln8c%2yBKo z|JS``ahL5Xi0>&rxos;PdtiP}Z8Q;mpv&ef!OMG>upAQe$CrJ;FG~885`<$scM>v+ z5y=7LiT7oT%Wpv=$%>ROTQ$Ul4Y0C;Hw;-{bzA}U76Z}PXZrVFVKThqvlCv*Y7{kK znGv6zMiiI*5n5qWg(P(|&lca3#80$`gj^HzBB8u^XzA_+3!rq>ljtrx!vfM$F6MJL z9s~^CGV0=uE;LX+Aw*8icHzoEE_kHQi&D^j#qIBbUUWoY4poQxSxQcnO#0UwV*Dm z=p_k+-84~qj5m?eV0#7au1(k;#%sigcpv6Ig11P07C`p@gwxZ@7btfkAX?9GI^6bj z^sDz{AesM@k?31Vf1K-CfFRUmFX3{;17f}0FFv>y1~UE2o+qbD{tWyqTTrKEoEE~% z4N`2pvzaLb@N#hOU|mM7OATvW?R@8cp}^L@Ol+(4-6L*Vx5l)p4#yCM9sS#Dz&0Md zCx&(+$3L09g@mT6hjnuV#dD2^eOn1>@nCC2#pxZk9FV{I)CN3fI{9xxjnBzr`m?pc zEC>jr_+OOd0-G@M=)E(^-|fgpJG)etvTEoGotG~nBo0DEuXE@AMX}UI0KiC1ls3pe zCFdIr;Io>ntn9KDv$mJlpR3&atn5~8mEW8EzAdcJ_l0G3D3T-T-nYIIK9% zcIp4i7n%5r5S;!m42x{>#DGNo8;#BobYD3VG3wp5vepE8w({-cmrupKHpGzN1(>Vi zK?dm&8&3%FGK}Fu7?F#}t(Dm^QehIeKYzblfKNJVe`{uT$0f)^_eyt9VRY!pb%~wk z)wXZ$V(vMuAUs7(dWf7+%9U$_b@taCua^)OMD`p`CP%<$+LW|=WH>a4-;ENScQ=@! zg+gRqnmKrf!%TF*2-34*?pI7i1^zufg3CT@^qO;KgW@2D5zs%I%QWMJ5RI+8q$e5y z0S!YS3i|#?ZYi=Hay7~~;S%(%e=S@B)-f6^bGA6*<+_Yrrbc$zJSaKVUC%%Sn#$5f z`EZxYg-iW|cD$X|SerS6`YYQU8gBO$0zj!@rayPv*Y<$WLsFxA(*Xf2jvl7iiOwD- zHwXOr<%J9hiis%rLjx0^|Ih$tVT)aEaM87R;tqEcOcFTXRWDwX{-X--0o%Oo`!nD> z_&+F1pqI5_C?Vk9>1KHa8IfFv44+AV`UyLT#gqiL$Xv$j2xvg%rIN?2Sl0w3@8JF)tw_wgG{=b#ttUt)OQ$ z{EyG|{ugT8CxVZha(AN1rOL4tF!0vcPQCrtZ6gcw?d zwP(Z|pekp5@+Nla2Vw{-M2eNdELC~CLQo$1L6UZzKH;IySCACO;!x`OTZ00E;;#Y% z0hD#tK!_FYM!yVGwrqPzW{>@E4-u17LnxIbti+u%resMSv`-)h3n72O{96KB49to_ z9Mnno-rpulzYpF7^IHLo!d6X>#AmpKCUrnxo63v}{Md6)TzLtQt`!GZgr!yv0QX+= zHg-JKt$+MDQ8Jp}iq4#0OZq;~2AA6T^GC{WSAIabZ+jr?9W```hjylb2z`WZaZZQ z7}fl+s@nLuNb>8}@0Bb1p*DV_CdJ!pq!;;F?5{#tiedPOhT$ht3T&IF)*7=y;3Hk= z%{_Bg?O&gycvXE`#g$EUS#m9wiKA6tlKV@?LabjLrV-9cyWPvzMDc=~MVt&`Qp1g}S!qH>Re# zyjMEKMD4x@r_gZ=rBac4@oZS3p1x@c1ve($L8Cr1@^~3HX8M;L1vW3pVRNRnh@{*D z{xd5iDGxfAf!=oK#z?juj4iVAU_4a9jZb^0layb92Q`@O2fAxgP@7TwDz05~ig9VT z@^qyV=F;R8;40pIRwNQWevJYP7uQ?@e0-jF$4^HTk_edK>L{?p zV_Q~_Mt*K$Ny~%NQIeB7iF!Iie@Kiu9o|1kq{Nz8Ymy2mNnSo-?aX=B9#4n=l0^ac zNWZ>q7-`@=F?c(r`TO}#&uMMk-#Pk9_m+3+DR|5w?Ny_JM8`}Ag%&RB+mquy zN((_@l-PaI=-{FYE1f1Pu61;Hr{AI%*Jb^tD(7aurJ*+SuWQ$QY~Kl5Q6nukH$T|l zZvV=Pt_IytgOg(*w{kdxC^5+dpMfT>juHReeKwZZI<@A}7zIx*W{7bcE?Rc@JYV2S zXx}G#O>2T%audWTNW0w);FnX;s}wCDiLc%MCS4moQnY!}md1j@B~@1{*G$EgjEjS4 z9S%VEseHTXb0-A$glrB1l`K@2wv!ZH^AhQpTsBG5P|bR?Z9mbN{)%=2p9_q5ve%U; zKP5)|Ih$h@(G?vbJbx<1(ba9wU{Lb~(sC9ZmpN;0%qW4QIMF4_Mv`)i{hL8)C^b?6 z8w)Fyc75N%g^Z}YDX|U?3aqs+TG;|9t z!6nCRROj&^MNcgVSiKtE`n%}r5#lShbFS>F(NJ?cXbN48W2S&Y@uHY`?+>#i9LmQfS*0<&U z9Mzrom8-?F#9@I5D$G-VA9HM6f>8p`QIZ1i&)mzVcR`y&^&Hm$j z3+&Aa%NShNnddh*XjPYY%9(%vXM3o0dff(b<0g+<%qg&gxOU_$Y%l%VhGBsTXynM} zXNd&`|IBu}PKTHCf(>G6!+|GLIow#&Un2X`5yA|VUjTgKudqQB>Z`5Z*5ejX(PG4x zh6n6^T^v@0>(|;<@LJd>zB8_$ z%bcTI;mG~^@%U5rEcSK7!T!sY?U#&ZI&dY0WxRYF9Hp+hyjd4BvDy!RHN!JMm~22B zmvufoP1IasR=S8p0FCh@bK^A_*%|K@izF%cUjAz8?s!5B&C|{nxNtxHdqPs;cwRus ztp;Kq7HW=jjdfF(uH-r*q01A$Vd&>W+3$^WugOo{wAGXONb<8+u=DBpNghlBto`2` zQ#rTL@(OI9sba&zWBoS&xh;zd zFLXr~af)>(LE&TB9(k{iDhYj5WWr~VpCX?Uo6y2`ry|_A7A^u4v&q=I2|^ZM0uHw& z0V619UVXD&g+nF{XPFB*%Zoi);$bA^Da#8~(r5da($T~MPkS2Vzc;>Q^LZ`y-Lt>_ zq~*1+*3h^8*FJ=iXDtqwPBzCTmG4$eTn+hcQ4|n2gu%Jq)W@Ml8<{Dv3E9d2*Do^Z z95ivRuM{hiKK97(x@QOOBo+tt=>DW#nrefQOk7a_ksMy-sF$|+mk z+L>S3fOw1P<%iuIyc|=ngM1XBxO{0DvbPyulnc$ENxniOi&cF*ST4y-B5u&DLhHf+Bv#W zTZB`kSHJpl4e>GK@DZZqNggP52&Cn-97b^W=DHHX(el|viEJ*eQ?ooV{of9LO2Jd&V>Vj18YeQ5YlZjvW$Q1v5tKlXVZ@*4PGl?hD{@IJ* zi%{dtLlxh4G{FsBO@w^#As7`Kk-oFuW~hm45@4|x)gnW#{psd`7D}w>xZwA1qR-hX z7S3FI_RRTJ_SgQs?P>DpC}mju-+dXsG>{clhMMPea*xc~ha0O@qQly_{0`hzFU#nL zoU%QoYQv2+uvhnrdlkA%k~8S~N(SzEM)3+gxikB&vTl+LUZYXCU5suSgqxF@2U9(H zeHyO02xDBufa6!DGuH|(x%D>`YNck9z3LcrEvR-PiTJp4Uc3 z#(u@Tg-$#_Sqz#sotS8k`Lt>pBou4x8V|%Ttk$pbqVX;ND57K+ zc{=Ff2|zE0JUtR<4m-v0#p0fDk@ta@Wo9Itu+acW#95t7I=~`u??5?t=nf%~;C~ zY(#F5fA^BXpP;{gZ*Zc;SCvB57eXx7otA` zT)cJLD*PoG)PgZEq2mZ3l=k4)#}SP0!1?(w1WsU^vQy+APaZgwpAbJS7EHw4`XHIE zzB#>9D=+#>a_w@rvVz`B6VASxfKa`JbM-q|?rH0;tpfqgmJ zSN$zQ*@aD!8N59jsJNjgVysno-}h~E14Ma_OGV2@!2=A&WfovrU#}5@9^Bj}jd~ye zYGbdu%>zHQX~LIMAXfFq^&fAar1Pw)XWUE)IcX(5n)>8;aAAZVS#Agc`{U=qYJPFX zjKM&W9?6I1_yl{|_4WgfH23>f!=+zP?=h$jjc+oQ->Z^*pAP2f&^siF4}V zTJ&Y*{U$icT~Hex2XZYQ)Ojq`jME@L?9IDmd?f{t!*gv~0zmFo#LTevEdSfHs~2zw z4;_h{$_PHbhIf+!(A%eJtZR`B!$mg*;7B?|?J=R@bmO@QatL?haYp z`|sD}z5xwpU<6zhclLQ&?8Z%6#wy;eD9JucY04} zGQX#`x}D_o`MO129bd(ldzxo(p)9P7p2Rork0%lrZV(|{zvpcMK$%^#F}d}yGEi@( zdNMP1rHAQ}HLEE!NPsNm28}=!nn~-G$iOeao+~JTlg1haa&8X_fetqNaF!Y#Zt(Gvpf50jQe~Ef zuP)w7kk4Sf&7l@|nyMI_YW|@&ceik?t5G=x!7)NokA2pXV$Tb2FfJV@*YdUOGJ0~D zKucAOrj?ufjfD`4q-qyah>kj+8Tx@Xd5pO~y5Az%1K}M}%bemj_oaAJ9KR8osJ^z6*zc^X3uLk9Ib~8(GF4P z%UAjkeWe`$GtyW((k{ z;FX=`-s~J#2-?#o*5PWF16Y zh_5UIlUd499KogHl2G*$z|dYh;NzC}N1UHfuJ6@SK9j^Lwh?X`hu%~6k19%}L9XKc z{JdlrgSmm`beSC}&6YS>$Qt!Q{WP)q_Vg408wZb^y~EvYnWLSM0(Sej-tklX^!sA4#5adWMHj~Q+}r|H4zTP^sCiT)rBl8bKW2lYoW z1$y=HpVUtvaD}|mzNMLkUeD4F4{;f}wJCSo-Gb#wq~IJ-DncBD3zd+7y4Yk=pp9(nL$kxt!t+o$u#+gJ;0%MF63Bc_g%R6tE%DM0fcI6dm zF3sGxW1<4Hr{OnbX7Wovmz+xDDQ=|c(wKB2ys=(r9EjF6_%!4>TOe|9v0W4|Bs%P@ zof+(DNv<{S;5j_x+e|n!A3wjP12QTE#KEpRYknW@`bm7)6qQ$;sk8&6mwHE{7qJ=* z2#~vdFS(xCG6Td69I|wZ3qb#w4v*$#?JUvY`hbDaJf^r?=X@Kt7jmU8jIpNv-8aA;AL`35cLfhH zvelN7yr&K6)^i;*mAcKPVuhK2FEpPrZp)E4eUD#>%ML=YY^quGTGBz3w^)422skj) z-q?v)o8lrzewu=M|90x0lOCbvOtHo=@`O?>3M4iXJI=`|6%!6SO ze3|c5x*q_tFwS1`PfC%OfNRX^e6I_DD$B(4E1=}!oNP)+=Pfw0tCI?)I36g&D_b8t zas)0d_AOk_mJA7q)HmOUd3E-_U6QH-!td7);L2Lw2*ez^^({+yliqZ7V0%w-(%^taiXDTYt$^Wm*xGyLaL@K3UvYA+LARAb z3vw;~TO3jIC{gjSTO@!k1WqdQnxJA5nPT{it(F4?xz@^4F{#3vEbQAi7M=o&m%nsO zWt#2H03z`gxfavFQ$h9^fHNV5nB#ez28oiN!Q)+VoH8)EIpE!~*o>SNpL>%r4Xgn$ z8=~==D`T2o8Zul;JpbFE^RuJc+#-vh@O^I4%AzfPU}F469M6xu_kLC}`o3qbu0DMd zVR46x`Clh<<%*-}i0 zh2~rBNU5a{9Q^NJkB>ht=-;d7yZqeC<;U{(uWMToq`7>iYBz4PJ$C=06pf5%QL3iU zq9C0TXf&yPtN!Z7H09qP`@F{CgCz3IUIU^UI)VK+yG0_-Mzv`W0R=jX99vp+SSIlp}JHJisWPY%b^s^936B!K>PSDiqMMpuI-(DrokL^yQ`qWj$(>;7@6< z+mPe4>yvS2b60wHHdjh}jJkUlnpqq`R=OZwX!tUaW&+)Bk9hQac(L>##NeMH9!)NE zAu+Tq4!91QhZ87t?6==h^1pU4r{pcu5VCh^UT^KmR!8ggw~HQf`^ScWt>Fxk9+cKp zau>6^1cCvIah(CueF7*XI1kyPE;Bl%08A%BX&$R@{)Cb0G#$r4F9wFDorrZT|{)~!IR-iBx#PS$Uvi!>wx*{0>I|&XT9c% zhiUx_Wd9~1kgTMJLQj;GO{h2lpue4)ow5iI(8pT-QDTLxi#p^m0*ILiQ}VodR9n!Z z1&h%FM7!V*mVXG!Bk3U0pO3-S6~eZx3J=Hu;cJ}9_3YHn(S|4OA^df>2lByXhUb7# ztojzPu5(>=I`ltD{rS^ld!BF+joz0^m?0tXuHU{ka6JaPqMQb)Yvd^J1llp^(q#0$ z1dzHDVtpou-SFkLz(!h6JvjBxOQqr{kuSXfg+MT69JV=hLVWH@hMzUDW+`+7OvSPr z@tox?1r%-~xWceniiB5%<{hXce^qkdrfY~i2I{NidKH0PrbX#TzaHdQ7m!|FnE-)B zQO53$axk@UVEg+msfTX4=i#qL5C66<`hTrUD>pLHc1lZ`*Ze~mi-WGAU3nv~mh@6= z{dQ&*AQ)&^EH3=>HxH1QQ!6rYay?P~&$%lkEqS5o0wNL*Mx~uVZ#g}TAefD^^h|0y z?I9p+=qc>~r*VEAg`4Mps;!6`X-p4-uWo&8l0#}EXaEGqR6CL-2w9iIH-H+8EB!3i z3T75c3|l!3F#K10{I#Tv4B#oO-Q|bx1Mr0T6l%MKxKE!kgRifz8uh2NC3Z-x898;y zpMqE1e@w=3#ckLnR^PsAq7Cf1CFuO3zU0`5DV7w~hVLxbGPrNlTJg9g^Qz7TGHY8goxF^~nD3JPP}zO(ZdG zPyTtLA~1|e_lH*n&k2QOHogm<_+9vpo~I6n^n!F^oRywZcuQ0yhum+91N_tA($AID zX>}!6f3g2HzJZ0-h*Ec0GUX=M+8`eC-2a$I*N^^ujfsrb8~ayDS{ho(gLe0_jM-(l zwAGT2{U#&epO*2zR+1OTenVjYYlMS^me!Q4ZTBl+Q=F(j@%`Zb@BAwef9>7B0`cpV z{3{Uue-#KvOA^qmOi-K%s$;G_NZlYf_}L_TOvX2=u5V9CIruJwn6gPSq_{Vbor;S! z^}Q~cJ4rBh8^$gZ@%a4mJ_CgvcWCey=veGtyM?*O#OTyM9N6!tS&aq zCR)YoC+B47MJR6%XO(LMT@&qfZ{HHF1Hy)+nw`{Gc) zGdD}%Hr)vJSQ~b02M*>P&<_nUU$dmP7G<}Q*gxBDXLQlt{>;t_!Oc6K$6>3m9$ti2 zIL2UL$?A2sq)UP6OzjAR{{52>U}~zH1Q^ORnAo#k2QCM>t7k-P;|A_WsYEq z)=*$st{j_UIe7w>^x~-33+<>%`Llg%UL18Q3~0Hl+_Eotgi0?oHZKa=tcu~ z2+T?_9qM1u5g!xtba-~h6~qY>`F*C9M_A;uQ+z#@{f-3OVQB95NMd#y>e@BwwNb4< zmEtvj-D_?aw4`jdup1zRw=ECXwu|860KG8;zT)_1BoaW}H&tNhq#;6Qr_m$6X{+m_ zfZWxoBV)6+ldhHsdqbZs!eqx{5fKwY9mWaUZe8=yBrQ#EtdkW~_VkP91>i=fJMWQI z=1Gn2cTf-J(tZ=KfksZ|(0Nj}4>Aa86fL4T59vGYlvk$kVerer@zX#x6(snX8C6Fx|Je zElFH-`m0KoFa{s|!!vJ61O#7}mQwa^(54uucjqJ~Pk|aJ5&ZfGQEQ3Jq}{O){yy)$ zDzZe6l$q;M&$CklNTe6C?x#Y-Y8RB^@y9=@raa+Dc27q)5dHSNoPIPM@#?^Te8E~( zMHsvn!aFx>TinFp6gj!&1yCi97zuEtbKSK52zi&P(xFo(?rB|N9Wz;xE%>dGwYErg zN&Ov-thFWQo8F@Dd0OV8G!IhN<#`5h&48@uX3zQ6_=ES*LSa)QY_ug zuT$??mH9Mak>nDi`opo~}ofOmi~cCt;X(*%UaXI0?Y~O*Rb;YoBi~zI$?vVUWqH&aLE2 zNLm6mWTi|{q0hM8;0#MEETZKH?g7WAVAfxdN4s>k5_# z(Aq6*=j@VsxK-amaA({7%>Lf0sbm|vQ_9vDca5T2UE@)v^!UwfFv#@7cQ-YyYCvMy z<=4Zf6cv1z2VglzWH@MwkTAc1-KJJ?mv3*1ekc#ZaFB%b4Z5 z%VrQih14VIfw88toP=rI1`uD&&Owh{3-i!tsM66j9&*dPL7Xiqrk^zB5D3GL;I_YU zNENqopUykB17;6PA$n9r%cIXMKjPAd!m!aT3VDSXlmvNik!ihJkR$-@6j)Wga89Kr zVfc|QI2-EQMdki72av9);wD;JZ?$GPQiM)&9sHy#_K+I%jwz#uN8PS$6Kt*gWPFKU z7Xfp;Sdgge@`*k6H2i6o*DM$vu5MHvablKz0O^r}iKaSz<*lwu51gWK`l=iePIeLR zy`(C7y{DcPGhOc6DRabSn)-w*h)hIJ0xe@6yCk}K=ehmh2liN_Zcg`N;F;r8b+v*c z_MEkJu;j+t{*O^6_lIR&w7Ubiaw^xdQIahL8`CX=2~;~6SJm;|=?y(xH+VE=Qr!69 zVL1C1sIjy)g+USjcED`ht*0F;LXU@ve;xw9GI; z&w@6ERaxd54-CmuSbUaW6>Lw2$}gK>$xdJ@&$q^8b=dECV5ZZ-;H&x zpV;xN9t-B4qn0kY24b-<0*f_!!q{v1K-VN2;_S01*cHTZHzt>*eruR$>mp2*cDpD- zM{h@MNfNs>jV$2ms%mkD<_x!iq$KM+1#_PZC73TEUY{AEX-Es<8B zhyN3DRZe65x*R{*^33L_kdI#O<%5a`)A9{->=zz|(|ADnGlmO_IaI zsyv})oT1&Dh`f{F@alJo^xfOSi-O4+Wke?S70!_Y%JU!`(ZW!o&wGmMS=Rc~1XTP? zoDf(f{p}@{=t7sfsiD&`x9^dIj4EUcQNEUeh?y&i^-x=!lR>HJ5JM{)`N3-h6Vtv+zEuPVJ zkq^7FDF%GcqLqfymLKJhH#n&F&q{CIRGlCNL1|+z@w~n6dGrla2aKT7#IxwpjL27* zcUR`KxJWloqOzLZzTAD5U&+-G*{7=h<9kNf;5V7*0Jk8cXb!c?G(vA(%2kU{V_l_d zR`_hs&5SU~L6d@194tzU#)SKsXpg56=A>Du00>e>L`mz zh8+nv(A2-8nqp^>vA5_PVk(~$buB9u9XO-g<8W-J?_){8jIQ0AuYpX1Ee&FqLPcqi zV~oSIuG{EP`|6q3!#3OljHK2-)nDnv8Fc4n;>JkVVtW}iFnzCp>2rhhUs?UZ6$zAk z2GBK2yiJVag@R7 zVWxc6SgZ$K+jEw=*#%d2NT%-6xxCYbhuPPz^ubE>y_>DvQCL0GVKr;Om?d9p_if!; z$wD5etu-d{J(@aaP>xrR9Gf;fO}VeP6x>7aGq07&i&e4u1ra7~li)GY=LPhw3TrLRw# z@Wiw_0dCrOl@0ew_dG#BZN!n%&LM%ARHn8tAuH4>t^h3Osz>rdG0;1^hhO-K=rnVU z5i@j$j$`v7;f4}=Vg12(d%+5LK1a-y@&)U*nVzbje!9Yu;;l7s-&o~4-F7NwDPOqspUay=OMzMo_0 zbjG4>TKTH;c@0r_%G6-9qbM&(oV0 z**}|`tdRf20~*HGOL(Lf4isc>7KJ4q5AEeB zhw7d$$#OQx5Z?o+-vBlFIqq`G&z|||3JaM z2EHQ=UGB-$Na^E`Hx%@V*l=n^3+ieQSWq$b7c%%Ks`*#vjV?>ju~2aC8uYrg$Q)tr zWx%9YPuIEwPt%Z+>TVvZTwY>e58V8+@J@kRTTZf6$QHp_d8Vkt4UXN>nE@w`a~w(uc1kk;X!}_bH7u)|+qLvQMS;*(8IMW9qkRJrj?n<3WXXtTHf);Zh(* z5^LOs(I#)FzG!rqG*$+5tf_g%4=M-RPFA3X1xn`cFzgKvhpykQhD53NN54&eao|gz z>2)Q?DoLNsFQg1jd_qG5U{=Mri6`$4Q?NcSX%nY$%_f*;j6U@an;@Duofg-`ZF9LI z<8+wKyl~D|F#N{Gx5)Xlm~E;C75b;cikCp^QGyQkr++U|&widN$>kk6M_FTwgjIF> zkmtDHEHh+0sZDRipyjS851Qb8Ie0+_r4*M_*F!T14sP3dBU`dQTqXMFii}lBgv~r9kIw%ofReh@p2FZt3{|E128lsTHo1UL(lX3vy>0{dfJ(c?6-5VjE8Vk zAxLgN_=O7HrH#>oa@*1#IaeoKa@6VZb2byEfMG%QCr0cn7dhbTTq`B0JhEoEVcX)% zopN?GTHLimPFt0^n4pN)*1{|LX5BWNf^HY?19s#ME{*h-@j%wh17HdlSPxsT$e1^| z&_^=4miBq;tDXQtRPmv;Dz6()K;unp`r5LejblavNOflayzDC?HXE!@8Gs zk7XdIRITORv`dhiIouM4lmIOe^XRA!{xh;x z>kV>}DqwkB6XlqVDbl&(3XR6*OB{63!qa~U%V8SQUTeo_q@&;zOd z5}$W)_+5n5?6O1}{+Ko3LdNMMJH*DCNiglyUK?{q`V7tXMH@Z{fxzH&7f#KspN?rjkbsikMf-KTm?yu zXe78HRyQ|{rId{~vZ+j?jjl*@>`{WkkVcJOhI`K7gL>bcIcMV^S(GD&nwrCfcSihJ z8MHdVslyF+aI99^OW2B3@0554NlCVs0>n>?m zThe!XHFgb)OT6_<%y=U7Pu??SjX$|22(s{J)EVbvb>B`YYh9a1ojH=e>AI}T!dbywkVX^^a3zz;O3L{GTo6?#}Lzjubb&wtz1Q@C+z*phYaMhdaWU; z`noyfG`o^Xi{>sUi=eW$^eku*wvXr83mlCptA#RshHt?>XbZ-#+SM4jb_?pOQ8uZn zp>9?-(kQdp*A>p_lD%*(rydfjAs`a%5K5tvo8MvbmsLBX<6%+GDW|~59gz;8@mn_r zr(?tmE3r2G^`=mdho%moFOYeYTRocq&Eb z4b7?%S*fb}XBhkqBV=w2sK|+7SQeC)D()F@+B43~fjKEfHH9c%K;JMd^`z|f`kKO} z`hvGuf%fZz2KiKPfV{hvOj7-wRIMsUc&4Krh`Wox9@@ItWE*x@tb1o?lZSE?aJO2q zROwbJJr`d#GHojJ$Pae;siX_Kl*8yNS~1Tqt6ic4UKM{VWsenS8L}HGvc& zv#3LipPWc5H-JX^BMZf@iJ2QzIW451gGFvlt z|I`9{<$}zST#oV!!GMA-wsTCP;8P^q-2eGd&_YEq=Iuuyq+$jZljy+wt>CR zMNRJ%Q1V5W<)EtguEWA|QH8dK1A}%kWxOk)XS$PF6bP_Yd?kiKJ=7O8D{X->8>B!~yr&^*xp7Y2&Y&c}*ws zQQUf!=0kAz;k(Zz(5gy)OAoX?#vtYzBA#58;74`(s*>8LC`m%2ZF)BLIn>}Q5yp=tM8dfDNZK8Js8bj7f{;HGYWBx^PW1LzVJ zb$4!X85RYbTgx-vE5f8KY`yg6Z;W+9`wR`$EY!Ep6W5(GtA^(`6J4}ZdX{BQv2n7( zR5{3GMhYDGkk*9-ZCuH_Be7q(TZp>l#V0~;Ws%q~_aKZt9Rp8cTEypB&bvptj( zP&JR4wJliyaSEqvi6bz6kU#>b0cLZE0M z)d#q9e1ZV>+IQRX#xn%R2lnFJ$6ppSfE70XwhX$p4BQS=BjK+c^>?+DpyJJLHXM)@ zh>RV3UNViECb`p8`Ddy6%(I!aTqD_&VC*J7c2WuV$^x=m7jo+ttOz2I<{<@|C#4pq z6u#N!Z^(Yia#dN&8zkbtju&%5MZdo8l+`8UUXaDQZbX9pZ|YQn%V3$6h>Y}jh|PDj zLBYU@5rdA|s}eUwjZdaMJx8UKndOsJj5d@w?on=0y2V@6pNKn7)(Mqtdricusi2Su zaf4F(nGCL)T-g^1Bvj>v7hqeG*swMzXdzi2!S5WwI}+8I-ePF2XY3MveIiPG>;(Fo z>rs0wQz6$K`}{2cOx|(E=MVFeqG{Exr3v=NM-ZLa<7`kmS&_A3>wvK=%%S{xvvLzZ zvzFVJ#!WSWZelPzz4Jg@``uf>8W(C4yfcH29YiWcwn03nS2cVu;Lc=)aS;bxw_iSb zUerI3)f;e@?Qb6+BG?j6+hq(R?6>y8@{zv;ujIB{HQ-m9>t|~Dy@zmiy2IJ7&2_={ zSsk7~1yAuW!TYfh(R+GYOdpl?^oXcrX@;R?T0k2_Y!f9xT3j@3-~7V5Y0?YqoBP%f zUa0!duya5!*Ftyz8kK2{d&A?{ zM^}z5p=VshO&yeQqf1GJ_vPUydj&cbnCyD3o_DX)7jC|GX_i--ZM8NyYOjQw=^-K~ zN)jdkojUT<|2u-t=VR!6bJp5(XSzHqgnV$=d-F9qF_2f2r5CE#Q9E^z^JpQPTlxBx zhpw_AyWAK<5FLKWbwIQmcmx88$o`LlgydL|XWj_a#f4N=*FWm`8C6p9dN<|8VO535 z4nXKWJ+04)kPn97dAq~giCEJS%i9vd#*e=7J$zo@?7M}->vG+i9%C|o+Jj>7*I%i~ z8+*m~9sV<16tFqtVc;P}TIx;`74akL#VLp2X~+Q-nfw`x%^7pyHav>J;)*&%b|ib7 z9t#F@&>drutf7XZOK$Y#jQ9>0xwVC_ZcBG#O5*zF`}MU_X5-m;$A2zG++^u|&G@wi z0*~x=s|CxHoo?9|y{`7>UQKxO58>y9>yNC#ct)4lt3Xb_j_(ULst|0pI*ZfJO245z zyAkI?x^9TyX?AvLD|bG)`p<2+0qaoTotN7!R z<;p4)MS^0qt1$L~AyC5OTC-}M4N~Cpv}A5ZAJq}5#ug+e_7My1d!pf(3kpG63$By# z7K2|0h3tNeHYkw4RN^IUIfLR4dVcm-Ro0sJ%qRt?ZY7R^Y67QTK7GLGr1!F@WYkNV zMoGUBRwR2bewu_@EBP3GQiXXxP?b6=O!wRdWuL)q6=ULQ%#fTYHFxyE-_VL*Afj{!aAEokKWtDy1CSio$7^!v4gV(4Td6ZEXY70iE2fsm9y$7bGeK}vbbptzI zU=6td)%#okPQ|=NapN;teT6qW5I~(7-VhM6;xuJv4oeoLTL-!9cbr#z^AbDiKI2sD z` zgRSN%uk5~(c9j!N`HFyiXbWb5T*pEDBY?;XyE;9rPZ>ME>hkG#2GTdLQeW-z%81*L z6Y=@H@7)Oy(6H7yQvF&-J(@wIc7wDee{`};{$-LyeyCp8K@&^GUW)?`rgm6I5 z)Kj-v+id~mV&l91o<%oek&a1wQ7+H0x;>&IdqhBPaOsfJY|A}^qkx2%{+n7mIr#ZP z)88bKqTxkltVtC!XcfTGfbXVU_g0#@qxfEfQ{blRkv>e(eWqwj7jpx89=#wvxN4^$ zmwZ0!a1`|fY}|Td{YWL3A7@$%yr$~}t1#7xEW!7fmbCv-U5-7UjCNApfOoJ5=H^ya zFYRFK+`p$in@sEr76&@-q=^HnGE=a`8b;9@_8H<{@+-%JT|ZuqecSz+LTY8Gw?9qp z+29Nfrr;YN6*kLfGl1W_;SyU_Bs1*Y_1*Px;Y7`8Eh?$3wFF;MkSg7yroJWlQmVapH7K=b)nx1v` z*vx_Kj|%oiVYYm=M-G)=17p-Vl!SHeilZih`ZUpoMd)b!q!Tq)6sWGIWvyk>oW?Eq zjDpiIiZ)s6pAt8g6ie2J5Yj!&j9#-WUsan=-Hey6%n#QxfcVb-j~bg;v(l=cU6E-% zgYkzK@eBK;pxzl4tZw1=>LS98Y?2Y#{j;UXQVwVUo${bkrqveHm0Qi?o<&@DHSxu; z)vh4T;eI85{ZfQgMN9?I)g;gLDs1~7lp6z zm>*#DZti8i+>SC=H1J5Lu*BDp7r59KC-5G$ziUWV*Yv(czdIZt0>#j6Yx1K*S>vh* zdMdZ-Dd{N~KQ&fRtDdInbPTkj214l1eAPv{VC!7+n?ZHjD))-$ov2~bwWGA{47=LL*r zacNQF+S{XP|6P?4^&FUo6u6p&4G1X+a zXOBp|!>E=*ft2v>my(!g@qO`=qNC`#72d>S@Y&kT8ATB5uxzCjkQMCt0h><`2U&>& zCb!Q>Ddd{RuPke{9X@vY&S%N3xr7DssvNEzP+Zx$NU0+y5E(>6=`5gCGwqTUR~hk1 z=Rhhm?+LK?i`OBVE7j9je+Vc~PmoJyTx-Oz=F^wtb~f8`fj?zUegxrZM|XLZK3KnC zO=ke=U4ivvzf$W=f*MN~P{xK{8#}u6_RxthIHkQ60_^v+3m_du&F~r5vWvE>v?lN9An39$DkBUDh&ZE~q;hoTzql7$kU!ki(;8b>h_#9_1QC z%bxu<#zhRx(K#f6WhnO%Ffgf-@`(XyXSSl}+e^ zSHR1qnJv}&lsbP~5&LP`Oe4hs^=P1wA;NH|5shCkFR39^@AA~E=WUr5oe(FKMP3JC zJJhK>k3BHFx%||n-q);8j?AnK6kJdj?LR_wISuBHJ!Qs8u2X+?P@u7BR$0-$uw$Wq z;jS8RObFy@nlh;3S~{tX92|t?numtfQ(u|A2Z9-9nK z5MykE0z(fx#V%nTZuRd1#h3tU1_w~@3C}m4-ggC1av->@q}yS3wy1ujxO~My5rO%r zC14Dn3p4HAov$ViK4oDiDZluEHX>d@yi2}ovo`fw93Qm~j}bOwa9~j|#36(D(?~A3 zm^+HIm9DRfbQ9Mf>JP0NyMZ(cNc-SVc_dWzD`-Nz{PpT}{7(fGO!Tq8*qQoBavM+z zaPb$(5!Tj8$9f-E6$))OOYLepQHfRM2nKUeE?>5CLP6AO9fZ=_PhWtGE)#P2>`1|IQ0&n$?}*P?ia$ z9S3I+6n?pi=3JU0RDcY@1bW@u4Z7SqB?M5IsY92*xAiJEQF%Tng^o~?LFRRZ8(o%| zdEgbSg!}Ezl+<3;gx+oz!D8j1M>TwnBWkNM6Q}J_ZM9A+%2P6uO*m~WoYcFmJV6lg zb9h&C3qbBIUSA&2kHO5f?d2odkK*=UH&1q(wlU%jJrV;>v$S?YAr-18S=TUQ<9;CN zg$ci4XOeytVK?$EOD`5Z0L7ejO+3uKPGa~l&KZY=YVY!T``>6^)@Oj(O4U)82!%)$ z5ea2eN4!(&>6a$#`hxAOSDa|VERC)?lv10SdL#xj4AkuA zJPOZ3xAbL zjnpA;{o!M6s1!uCKxi~TDV)N6s>@|xT@GjTuS$?i&-gdR`>vpI7%Jrw{K95;5hUqw zsr;dwC79z^Im^N-yTtEha-iBJ0lXonwRPq}eieV6x8h-i`^s*lbN_k=Z0pmP^1s*1 zJQjp%a-th9SurVv!?f-)?yp4Axbe6Q>Ru9z=AS;f|KrXmsF+2Yo67wz4U%NU!C-yCxW8q4|PRjzv_zMH9ksVfA~0ywEJ*yf`Qdr z%Ef`@a32ci0ssz0m(p>hK+wZ*R zol>}yN&jRiVLU%TQcE0QSNoU0cV(ng*Bi%wd>Jh5;!o#TL_sC`2fOm_s1WTMED5v} zu~07skzBgNk3;`ZvU>FN5>$Z!4HqZPJ#2CeORm*e%lOtzcb|@xPE{oVt!=b86mvbJ z3bQi)phS<--IB&;I13xsSnF)NI(izsPS)X2Jh{g8xh{=kpIv+Oh}QDbe6*O%3{()0 zNl@F{Uw;hL>;`4d!>C=}H*Y~CNcfF7iWd3YOZZW9{{HJpGm$2|^zz_Pv@#rPxIh+6 zXA9*{p0O^X5>J5t;oXhNa~jt{gzrVjK&40Sxd}GRuJTZx4a>QGNaG;sBF)DO(6hp1 zE|LxPLZwrsAa!bL;;rXCLvi4-7G+zq1ddY!sj!mc%pc$m?UHjKPryFQdGtPSID9BC zjr6kJ%^SBt*MglbP}I`~K~PDMz=rdq+hT`@NN=zAyPR)@ot;lVv^G?} zi>UgHv_qAT=&JI|vY^ns_C`;4bEWi`FV-1jaYG+>ggScQd(m&ZY?VECg?4N!Sa`yu zO-NY$wu?7FS{k7~Omg!hBz&cxG#A!R5raOgs%<+3RO&$p`X7(1C|z}ECBZlEgP$KZ zQEGaD$B&rhQCPUivS*y!>y~1r)RB^vA~}2S9BD9TXK*e4MEI!h2D>x<~E~d$Zb`o%1OSwK}=hV#fbQZJ!(h(lW%toO#XqnhZ=l zP3$&uYvCK`uv$Wg+Bd0vUj}vEy(D~!-)J(%8q(JzF&kq&mByxzD)oFWPX3Ohp!#dp z(J}pk=U$nx@NNa&BOybeLC%gH+0l-mf2_k#S&GtsOBS-+KOE}CrWzvknNUa;F=mi3 znN?kHEJYc%4+%I-+^6&dj>K4U)u*SfBP*dsT zENu9#*~w3A=|ZAU`plredVZ~~u@-}uG!NOQX;R}r`;uBg^>D6BOtpUi`TKt17r1;Z zNCCRWe5m~_vJdp{U+Q0HSAzz0On{YS45<8JoA<9Hw7o5yz!5yNCWiY%G5sGD0uWAV zB~sAr;8Q5#>b?d09TorQmYf*}$hFLeW^J$TL#=aX$WtW8`R0`=_j(>Il P{HG+ZcC%3Sj{pAyxUy#6;@YjKn#g(rJ8S4aDb}eaqR1pS`!u)m9o# ze37-&xY@edQhu;E)$HCH!(Vg>ZMLCU2hN&yM&!e1kt^g^svgNm=m&o|i{Ac%k@U>8 zx@JWL5e3DWk2oI=U`tt|7Dh_f^i&V#53-ZLll)#o6N$erGc~ogN-czjrrAOuiG@bp z=&*JRL+7eDj*+Cc=Vi9wUs4!ZVZUrJhG{o_g7ifP&%f{`3upR{{=)9!s{egWx~`AN zd-FHOu*J|mb5d`#G)33GzKf$nK27VboZKdLaF2e?B5Fo7N*y+NS+Q9R#^~|Y1U zf1nb0VD4DlQBA6tld3OqUsvDS+qN{4^Om}IH}xV>lK8`W85k=Uu4^sgaXkM1&YO;5 zS58z@h`i_0^!@qTsq@~VW|;6C2Ak&Q`Wwv3!pr&17H_x~PLyOZ@6B4>Q@~F-P zMPIZM)hoMNo3;H4-k9s4b4EQF%T+*B{W3-NHv+cCNpCTx)#`9h%&PMqFU}<9BzZ|t zlVkEbkvsniji)EI^g!1;d&W}swioTY--0v_{^!I-pS(e*b~jRgQKp23b^XBhjlwkw z5%01hSs|JW0v>nqUV5oJu!II(!4Z>054ujfD{jMTCJxJn)m)T z>@=dT?IENOF5U3H;^k9_IJ4;IJdVFSjTgaj`eO-VRYWDNeGaV~x`0gRUdAApu;yXAYxZu_M_Ied?3((f60*EkOWO{grsh6PTGIB)ML8PeQI*=%!{^M z4-XH~k>VU(w0Y!p67vD+^Ud$eJC247~pFTRdXPYg#7%jG%|6NcJa|Th9uhe!%2ySAy0wwY z*kx@>Ijk8ZJ8uZ!e63X!qgc3g1eTOSSL0r>eeE3^SUF#YQ|T#OwXo?^R7RRmozTaj6pZ2utmy&@ z+fqH$YVXRw$>|9>k~v;<#4dj2@^(;qU+PDqvb+n!%6qd$^+uD&f)j)jtP=rgX=#yZ zDJK4DvbKSnCRnH4#ImBtOOe?3Y^5 z71FiSg?ERqm~=LBsT<4R@?~ocPFn zVX>tiIukWh>-@ZerUH9od!x-6qZ!2PjajMg)DGVG&LqDX)fp=rYuoVY#m@4q9pi`} z>^zJS>eKu%3$X;SdIBqqs?J;HT|l&zmU9Wr>uPH3|%K~XPZHf!9{~QgVL78NcrZ- z$*Yr0&1x+>%u>wt%FQ{S^AP3|g?g$6Dp_9ybhn2a`x(ERR462LbD9d82HL*0jYVpZ zrv=2d=tYx7rx!j@OEwQ&;2V&%`y3ms5vCD3B<9>TJfvw<*;-+Z{`}<>=8rc~_&nFT zt|{Zb!nMW4yJky4d(Dr6oI)!wpEQ!s>gP93+DhJH-U&W)cnRlY(`S93$K+TNH2DX3 z*J9FRvP)z&JT(kT?-Z9=71$FYvh2%e9@>+SbB|oR)>VRCapRd%PQX>lO~A@w+EA&rVl zBX>puDm2`Z-P9||DqrtU?z1jesL6fMeez9rBwjs5#BErmmBZoPM z_7M}qbtCikJ?*^F=FyVTipxd8GuInLFMj&X|#ke1OFvxVRes=!R^CKhyukNyLyl$G#huT2jSbS%? zKuR7CnD}7n){Cv1EB05+t|VT}^qKV;zhX)-LXSbGaKrXykkp4rm+N)ZVi6thA3v6s z8j9){<~Evd%pDpZtPc$=6&iNh?OK_lBbE9VYpEBHdazi#XZ$ihF`vR%3n4d126N}5 zFXt-{YM9I%D<9oiQ(AUL7xKia?z|M|@9S?EDHPen>HKB)3uB(sE3;p!ztZR1=W%{6 zS;t!yPF(s;H?i0%|6Q`ll-StE>VbKPKfQEp*R4X5aNkloXK78|;wM*Fe?|rU4r;St zZ1)ykU3f}9!`5-(RmCfXS5(P2WPS=OSf?48?A$3e#!eAr!D2<3^9jZBl-qjG_!o0h zHtV$v-ocIx6-u`)+@62;bIAJsq*hkvDqf& zKb4pX*dAWvVXh*Uid`u$Oc-9Qp6lT5x<8}D9 z(q34T{5m~w`kIQ>d#n84(^a|gx_b?E4bD&WJ~(vo=nPZ z@+5bYeU-hA$qA3j-2;;)$;COhn~q$|PCv-^cm{?`D$Eyx7Ap@}mxiV`^{Li{%?`fp zI!wxUq@={9xLkKt+3VggZ7N!}u)nZ+{(P8 z9el@;n^&2@+@;Uxqit-Vc;U2lK-r0X0E40B7-A2)-E&34(H_X3d9#WB*{?~Kd@%j{ zX6S9&udY?~ec3aPGovFBI&Isc!@_YMQr$$mF8d_omtFMFj&Fp3gu+)}S;9bC8jTTr z#zaFuLxzR{KAizSLTAYT`TXz<1KPR6zn?`zdu@z{{^uGQ@EiIU41S<{j((qe=Z$s& z{NEMuM!Ro58I4 z90X|&uiyipp+B?HP#<1mV=73aEGQTKevPb z6QnV+v9aW1W3#unXSL^KwXiZ|E)_I_B zt!rg$X=7{wqlVUfu47?qBS=F7J?Ni*NBh)wF#h+GVAg+*1rEpteZ$7V%Fg!B+Td0J z=&yXT#t!;sDi4g!0nNZOgt+c-3mjg5>YIN*@z|Zp|Gx9~9gaK4Z$0+a$y*hy^{qrL z%)v8lg#OL1KQ|x$^3RO|Y|znZHXhkpfx7Qzx>`-f>lSi3%?L4c3fj2}FC27Uu6 zgZ`bt2mfI>`VD=qr~DN!1LQ*lP2$15XAWoPhc1?>>pKcBZw{kB!hCsy`JN*Fz0Z%* z74>dqAwKFTe2n*06`R9)!;g_EDJBO$!=gM0PknSxWX_jA`fQ;)2|D4|c(W^CKfHW- zAV41jUmT3&-yCk{H#At>T({=84&z;Nu2>5GEwtb2{IGD?X>KRv7227z=$MzOMPB@e z4^DLKGzbuu;Nbt~YoYZ%UcNlID)!%9`$8lL1HH)UQWo!jw--!I*f#EevFF2mG@SKR z6FlF0?Y}%HdXdY8|Arpmns(hY)tQuDrh)%~bpKk;Q?26Me?@D|%hS0pMiqmqxy1hy zTmGzF%`);|o)2?fS;R8EVKj>NKeGIA?H8kAOaJBh(4Cm65#73$E&rv6h*&n+|Ci@G zD@c5KaFzox`7c`j2Rc$CCiwrm^PzcAVq?OPr0UlHVab0j2gI7CQZZy7OM1J?u1TNTdy+_NNv{Y-QT&^N z9}mfsRPqdv9a?IqH${Q2n5h~X#-gV9vJkz9Pn&BYFePwutq^2Ohb+Bo<>5R&+V zWa2vKPLlBB61r7)IeHNa_SyE$$(7k7&K6@Sd!=#|YhuHsTffVlB%22#2Dtk?BccFE zZ2n3;xe_mKKiw%&G@@M&uiU*E5Ew}8EXbIP^R#pFHX>=U8(lZ_(K$(jUesUJ zCw20QX<83;Tej*IUQ|ff-i%8bl9_nbD+0s!(`s+IvPx}9E?B8k57hwv*g-)l= zPl^TY`%{&%HNK~sxwhFU3a!6AVj&gIm#mWuqn}ryRyt!EEX{}1uuKmL-aEyFS%?Yf zMQK!Of+sBn=A~EAzGX-Ai!rM+x!Ji-kqq^ST4_kqGCki0y}`-VMW`+w z3JUTE^&Hm8Lum(NSP|u%|CuO1f>FeG@#mA1GWuEbh+C-K?sF$su9C%s_KhJE?RR<5 z2{ zEtySA_uZ5?wu`mxkw{2L2tj=VF=gj$cRIbTnWJnBe?LPw2#VM;RSVM8W4q=uRPs9J zf9B0K$fQtByxz$a)~_tPa>BwBK(jhmRn<=d%j|4aYl^INv_{{seHgY6IQW3X|q^7l}zwNfP+P? zFhdv5ZN*P35!s`bJr0Lg`4Ta8*!F6KXBAIIX!FVqZfoDvJhjwilv=u!>eI7%heZpH#Ka2h|RQ%;(={XwxkH}&8$Z>2qe2rM;d;J z99{{u@9IriO&&pUhF0*0{cZZ14?~vc+(+Db*8HZRO=u@ENitl<`H@}U^Vc@0nUtU% zm%-_+-}J(cgLdTJS|Ti#TMd0ge;tSP$a0q~FZ4N1#rpls;~ui&EQRD%dK;8v*c zDPy79+^*JU4gbo{yrD4v;u|-nz;!kEdXJwcsG>9mZP zfSd0wtiImIVN{)InpI4db{i;e+iqr1?bj}swYi{-;hd44yJ^Qr0&pX!vxBimdI z_%`}<8)B{-)bP#c)O5t{ucvSfL@Q}-H!3CfmM_}sa>v>A8_x(XIkrWZ=XR(w%n=SU zKFMk2n@c2+x%*r_XMSru=tajwO>pK+wy*;M0R4SVx#j_S-XW=@?1)lq*^0}_d2!HtK~w7uc^<~u9Dp5Xr64%otYlq z1TA>Y6kW90?WDQ6dSpId1AEWealYq6!>djA*I{&jP({4L7oSDQ5KheET;H~MXU>W3%E%kU=M-Fz@*JiH0%yWk=`NHWNw zmbOEb3e|pxk585Gr`yiJNb;7Ch&Can@K!ZmG6QM-7nki-o2_53pD5q)_Z)KDSx~ww z@cTNRgdC~=P2Zd!y%Ex^SQ*cspGe0tp=eXJfQxyck*|hYkdb3vc=c^iVw>AWUI?YP z`(CfRbesGB+5n|+4ScMf|#(h9$7$!NO{~p=}ZJxQ_zRmZW;rW6#O)N!H;#96S{ifOF{gm>HZ}^`jOq0~LS_w3|wq)bCJB^c%M2wa4 z{J7$-Tnnd*`%pB_-(V$*MTqZdw&dIh=?T(RDDmMprmzAq)x$hx6R~o3|Hh{0R>U^&? z0Fbh8WY05FNnK_nwH{M#Rb5CPyg>C=)ami-FgG_SxV_c2RGk^2FXZ_+povLqyV0f^ zgX9j(WLwAp;oC1-TpM5p@BG;yw2^Do`La3_*2@~@rG}J|T5Z_@inv}jC72x%Y5I;z zBHO7uy}o;wOnB!jNkz`*A9VrFAsRYiUl3PUAa8&Oy3^ZRPtl%p-BXRDv`>OQwkwA# z3DJu9l{0jOC%0m6!GbD}zn;%vC$6z$ur~&J)S(qkx!oW5SMV~5b(nlhuko)Gx4E(k z&dLR)xjXS;yh6R^FH;#9?Wx=ws3fXO{1O?#WgH~9!JuSlc8K%MKvAN688_<+Llpy` zxBMW>CXg4m=4J)B*){9-dl!=Um&)??e*k=uXv)uco;>{S69L6F)Lixxav0({sv~nWpCIyYNIww(@+(Jlnq_h=}UL$XSYy0q`VXriN;NIU?t2b5!@; zCg)PPFL@Q2DfUV+CVE|q#YD%VoDZ)F2?0hCjmT!{$R2B*bd;J|u2??^+&aE}d-Ss< zEL$?1RT_A->`o9=X$o+&qXu2P)VoxnFecxmI}JYdh8!6sDi4>9;hFX18FtWhnii#s zqTFA89h5FN1RUb6`eet+%t`hx#6zmS%OjOuctVKJY<1&=JU{h9P@nKI{bZF&C!m z@y=!B`8JG)&JDR}M345=lUu02^dU=84odCPIzaXImiDEOJu0upwQ%Z=L#S~sUNcjd zx%=xS;j0e}9ifthGh>MQkDBw&YtbX>=wBMgqn0QG7UY(FN7V@z$-<5JlPfHkck6P+ zDIN93pV#d~qzQX!;iF8{X#}=@1i9r8_cCDCOPK&%TRlqH-EI6+-Ol8w;-JJfl<^1x zmzGLJ9%Q-;n5p@)xbZ7|-UZberzyoo<$5bzrml4LZuW6+Pt9(92&ky!?CzD07!LZD zh&L;CZEY1t@G?=R*aK|2kRtxI;QaF$;KIoBgekpvKw!%8JV~)SQ@y~?t~&Gc0r26x zy0EUD0U**g^SKSlnT7o(&0O!9Qa(7Dpn#8-8$?rv`9(c(EKeE^+E3$&33)KMS>;B2bjiafQL4pDMU{Kza@oF?&(Jf!A~Mvt-03Pp z7AV6>ZPVg*f76RurV7|Me##>@$*Ttk=@-XVXZ-9)eqEIdQe2r)NRwPphRSU^&x3mcgNs< z+`;bDdVY$a`QWEag8|E#ra*?TiLO*p*g3 zFBFtD;B`b3$#Bm3hCoac3af9|Zy6|C6wH^cwa!%T&sEmX`;y~D7uB8NXi|FFNf!Q@ zVsGY&yUF04)J-o{Y=1v_yqK=b{Ktv`9+a4$ohQUwA!t2nvQNWhrA{|lAV{lYe6jFa z(=#tMj)4wM=LLo4v~Cw3ZGl3NLpW>t2Fn(&r`>&8*gI38w8y(rOVIGLe}Bq-pS~QK zX<+{(qxg<6?r0sG8~m5%;sH>j_Z6$5+3(ZGHPwjrX!Lpo3S65DyB&J<{f9vG zsTOB!I_P6cu1eGf+(?W3H!Z90H)rAww&Ubg*kQKAlj7vHy2QfkpYRI!y10+CX+2bg zFni2CRe5Yv_*bStO-TBS(3GM*c+cwQvRfQHJ%%N1`(ZwaX}Ig89!}WaNo$Se=ZSS* zEY|hZ#OL#k{sn~?fvLCtaO*-*d@D&1x|uD`1oFWnQ;@Z?Dfx+0Le)E6gQ>J7m(doI z%B?y=p1x2?^g){G9>fDdcuK5YnuTuzO?{j~0H=Akz0fk9!Rw&NYMq`hRzAX=!yAP~ zq3PqGcxK^Ljjb7+Rk@EsabylZ$jN})ZP@YfJrrc9&r#psbU!Gj zH2Umef9^5c@%xJGX5&r%jk3csif$}@dC#@MD5Kqiv@ z?sF~%n+sSV+(9P5`sBwdmqDM?(43~y2+5Q~4f(LF*5+S9?H)tBav9?eeVM{zn@ujI zGwG$}^VxZ!&p)~0!Ne#gzGAaUWm3BK!5%J7Hhjxe&W(3i*L?YAW5A-4FpoD>(%O>A za3P)-VGHWONtlV!`L()eaa*q~GR-DXQ9 z0LM7%C|+%XtY!;W2Hy1b6?W%jw1wub*_ZEh#(H{*cSQxfDCO#T&Qyw`N|J}e+8nz_jNcn~F0 ziJ8x+8R|+f%y_e8GYTLu<&+yEk>_tBko~runi3|-XdIS+N_#E!tkMl6OY@ao${Mt*(Y%agB=UzW3 zpINYQcXkz=Wu}j@yzeSFTw91R&g<-$C*UEeFI?T}QrC($131H)uP}KNN?|==8}4(k zjCT+$wEg`_PiY_Hpuz~R4^NA03(?@L0t-8$fu)UOB+FJlI&~n@e3oU0v^DoqgOWEtnsx;xjqWd6<&1&(W@UBtnn-#q*_F?g z^|$88OY^KI8VNhg;_QbV>uB!)fJK;V@x!t!VKFZ6@8ETS*%&qty(Vz`T$sm;D1cz5 z9Ze_)oVnYnlmehz@mqGYYUz9SgYbrk2GK&k`oB!rvzzR4D{1o~%Zj&t#P$N5XmLGD zxb5kAbChd+CT)yF1@_q}&-EeR2dVj+uk=;a zUzR^q3mv}dOx-|UItqtT4`h=M`2rtC(J-o~D4C>uS`66+@VPM;_^_4FvOgAt5yYw)NGDgyZ!B{6!-0L_td4h z+33j%5CKeNVAOM^Uy!l=O>wNERn-sNN@l?Dx==J!2IMMVd8CEv2=Ab!TzP{^0pa$6 zbF+pgl0w6w^V*=V%E$f|f19aT`(z+hSz8bS>^CY`Dt-{EF{c1eG|TQZW!vF&-`~~2 zLIF%7UB0LT%H#>;K6cpc@ac&P{_9T4cH99 zI*owXFq!I1hWCXf1cjZBY722v!5Q6CX2)S55gCu~gxQT7uZkY~6u7r2RH^QKKrUSc z(ob|fam(Un7=X#y_5h0fNKWZixWoHV2rjlNa9GzKXC6}0bkz4%DQuj8e4bNh^zgH+ zWDq8{_KQ`b7isRzDy3}Q3Qy0j;1gqj-InZ%Wi9^wjsuxeFRsYl+nao4&{v$bK7q6; z3H~q>Q@F0LA!BvoNUq1*iB=!0pNp_zbd@`$?)4TP z+M0b6fh79|N@p`){)0w+^Cf1cw$9lCUPQMtgQ@NAvm)e|ySF1N6n@0f3(iQ0t+1a} z&jV;~PBi{YzppxL<5-4mA7X_7#4?T zO0q{bh+2y~h|%fE_|BZ^srH)6%>nfb&t2K2%+Uo95o%2FTYEsAs@~Xev!3?$xLhQl zVj8``uZy=}bg_#^8RVCsq0bog#a-tl<&KBu>yJf-(v>>K2fjnm5SfKwDocxfEr{uE zK+tmt%540e977bRp^Pg~4cnQd@Sfgr>1;2x!$b;OYwIhA>vaB=S4EiEp^}68B=!T+ zhQ_Qt>tBTZh*=&3!~6t4u;09B=xIigYJ9LA$SaAiXIQyQ;g7hq^lCbr%e~)iwXcvL z$poss=?LWaj0f&I z^W&|O*vD(PsC(Lcb?IM5zN#hFu4{qVHF+dq|KRt>^F@@a!LR+J^>0yzlko7=H>)0O zSR5!e06dqLp_6oRhH$V^rF0rJovhK)M;lV4pDT38+n$V0S#sMf)!n!wm5+N&|G`1W)s@i#l_bo8+^M15$e{_gAN9Bpc(Jbz z39ym4s|0qw;ta6Ly$z&f`R;0y{2&Dxr&)n29l>Bf!1g+S8pa7uj>AdDGmD1#4Aj;h z1GC-SPqfDtj;Sdo%d+?`|9FvCTNa}y*+D@w4@fabIb^bDkOu5RT%W5m+XMRVk2jAV z;(>3)DI+U(C)k1_^#x4m0)mG9+Uy{Usj&{4G8{M3wpay#lZbrgI{7xpMGpm%8>;t6 z{Sntq>0T{&*WBT2-ccr&OrCZDJlml`lKvbcu+oKD^9oRek%8BY^)o{uy{RIedi2{( zm18=VO!IM(izri|Ve*K=Wi;*9{l+N)+v^~^ThNKx;vlD2=G_|gYM?kctV}ga0U94F z>r7%u{d&HFaQ(IRoG$=rPNv!&y?~?kR5dzYnhiw|Bx)8TZ935yI#W0RBe%v0U{W(L zP~gCE88@VfAhPeS`%-XE5yO$4>frf~6uze+$}4DA793XVgN_;wwN?{G-XNea+#%tlUFfv-{;g!fl&8R%(6>t8nYfS1pDm~zev zNgfm9XCS~!jt^bxJB%#~Nb@4(X5m53>U)>c6*C`0cw8q`h(Q(FS%7%ikGdU-kc59X zGG#L-zst687?oZe?E%Gsr-V9W0|C@Z)^9W6?&CX?_vPlDTdhBY>;pJ~o05BGvwZr= zn!hmzlVY=;0#(-mFpeh{l4)%9an6eN$&4u-$ z6!wE0uHa&e!S_*Ap``q@yF|YbR>jL-vHc>;8j*_GEkVlux|Dm<;whM)Lz|$K`VMfj zRs{@%6&nTFpd`9Z=cz}aBE7Ei7n~a`N`3$QkUE*W`|PCS>pgX-synZ^??%B%CZ?RK z752R=VXU$=LZ1mHV_LKeRSqG{zF}dJaL^a;cN!%BOj#=sjY%sp&BYu{2KA6QN?`s^&jFX4tn~f6VW5P22LQW7=~>o7UAiDSWiaKvO{!URKvim9CTT0nMe-HK3HWtczUfDu?9@`eN_8vp)N$K zgK*^ip9nl@cnzNWRt-m8wS%5!Go3B6Tj_~Ivcvn4nUuH>ItHJud?M37fGi^!^NY0o z_n|nD74o}|5yX*pmWP9^ede7c>(#tW_{~L9bLJSaKBh%R|0D&ETfS;7&$Cut0JNjI za@Rv#U<`jEd5p``9a#N^2=kRU9@A>$AeDcecmVvV`QS5ms_WT^bF268oMc_q%0Mh# zN0Ez9XsV7Yyt@qNgmWzhEjbbLK=mD>SH+X1_sN5hAC4Cc&<#F7onh>fxK@@-^%FQ2 z4x+x|Lj`KX$SixJf`rMvkc$vBu`X}PWWvGbzTMQYT-)LWAJ;6M&}Va2;TwBHTR#uW z61Am8bkD;50|I0W6u0Wf>79g)0Afdstnzu-C3KAVn3v-IRcKWj2JmmPq43U6-PS9d zuyRy)wv3X7ZFj^%?iKsmy7graYk7gJY;_uR8(^N3qhTef;JgcBmQ0Hu{LVfZzw#?@ zv+`i?C}EvM?Ks4Y4S@VP-(h78Rp>xamz~!p&_-*Y>x&Pu1gSz4hJ}rL9}@o z$g3?9K|@G49uNcP&I>}z9$^^WMh9M0yV@L_DlXJmO;iA~#|lSXEc>g-<#Ck-YGG^s z>_s`)4^r+<-l>=n9lOQJo3kWx!oK3OTx|a^$aD|c%QkBike4a$I{7&vkkNqC)DB>) z=*eW|7N8!gv$6AV3Wi=3A7J4+r)CU_IA)6vK~HkXhxJ6lAfx&E+iw8NV8|+%e}(m5 zE{y%C?V!hMS649sv+@CTI^5@KI?W4$JQ}Dm#NmMkA@2roi({~idffyOl6%>ZU58um zxw3hx{ZMWeA>x$dV#Ak3xgRVY5aqoQ(@F>?>)I)&2`aQ{$)H_xP93;#Y{72TZV;+Es0SxA2CMO7T#T7LwL&A zV(F4lGD1=K-hy=VVfMiTV;mM2VLj^}AW2vcYC>^|kf$|X94r=7W~xu*80~g&0ZGtC zU9$#gEQuz^V;XL-=Rm=M?h*G=#0A7nigUYw_5;?huH!P=f49swKZ1(%&+D(Pk1G1N zfc)@1R5^jytV1|&opexU7;t7|)&N`I19r?5pmVzo>mN4D=!bj4w=_Yo#>g!I`=F^e zFA~;6W!1Tc_ZIP4TOeL7Q)kgE#UJz~s0+b}*X%Bf0rmKCfVnq6>%EW(5Y!ZapvwJ^ z2x>a^h!1AdgXf>%lkurB8xWx0d67P*eS@|f3nq4EdQR)W$@k~yBHQv~w$tPf+>z;8Nr)Qw_UZ&ul(wB%EPV!5=c7}Y&gMEJiL?&07#rjm zR~oG28-l76l&%h|-|35(QMM*i0PfJ|7#=Fg`y%iBcTcX!0o0y^JP3VK`MTyZNa6}~ z6c;BaUYx^y6t3k4^g_q=OLgY80zWs<%-*cXF}DYBzJU&t_y7n7MFICFv=|J-D53-r zMoL~QpXuQCI6Od(e0K6SWM%At$hw`2@jGtU_JH0%O{Gcj5vWt9wAl_M)Dm$kC39Jl z4OH$fO~!5HPdd_p^C-6b^>vIRu+4dR?I~eBU1{z6EvWGNVGOql##+2X!1+i_nbDv- zYW_+doWgDE*9_=9xVHKB?i2r+-EH8gOb2s7*Yi4nO@ttbNH-9IQB?=O_c@qtyH$H) zh~eKkt4zQmw_Lt8=GQp_>~;`u1|S{o8+c%;l5W(VU7l?KublbK`W*naYe{-d>Sq4c zo?F$75A~87R6oarwM20-xq?a!%YEhv+fw{D`Mol3drgP7iW2 za<6GGARA7r(KQC);q@)Z%^{EuT-2>cYS{fua$5w}^p+qp^@+6H$n3@;72N<8-LYeW z{-WYhIk~%TC6MMRIvj%3AT+1&l2E34@of#~g@U^At@vsDx!5plwz3=tLQTiP=dUTk zK*g3SG+jm09>kI~RmkPn!etAWp01FV0}Sx>%)rRLov+ZOy4B_sAeEDEsR-?S7i$jj z^Uo2nv!2+j5z9|$wTZ5O-eP_5>kHgxB~Y9kT2Puq!$uCj*0=O&(*%f(q~sD!i!y*T z%s|~{PaM7y)VEX+1?lespiwr4bJ!gO`()Np5m#aHKXVI5+;+wW-Pd^BIg{H}Kip`& z8YJuAa1AQNu=4x`Yk}k2Lb~mAPIN0-%S%l@Q=Ciq>C$vU5R6w|p7-SiN(XJe$q3!X zZbHst;W?GIwCp0M&dmNgD1z4nz(r5=R`vlZn+9EBqmG)pu6Y~Hltgy{E96RsuClS*DTJb0@IL988NOl8gmQjj`kVl3eTg^euV?B|5pl;U6BE~`=-aMd3>qES9zktq zjotIvUQe+vVIr&MwJzWscV!=MAJL=H`&kWoG9A0ca2bsNF{hTTs!rN&#CE2-j&}ys zzcZ0`qAe>}40N$GNgD3_P6Sg4w=b9ccuEZ;6F_#!&+UXUtK3eWd^Yk+n)nQ|iaA5( z@xOzAG!NsWMsI1;yDo1;EHD6x^FYzY^;R7K;y%{`7`|{pL@J4@fm>*G<-NR&1cV?D zxYgtSMGNY797rf(>zP_@prJgQHbLw9G5|B~Lik>)Zj8(7_Zfn?tp~0{(Jp6aJ+{qa z|LVQ&1QrCU+O!&NUGkvBg6boi#cfHkcKxYFTwm3)ormUp#c8?ib;C96Bp^U&#i+?j zOQ3ai)C*4r!YrDkHIJ8FMP7&yL;GQlT?h%mf+4?)OxNG_Fa%y?2C`vfSFhgM5DS=5 zX>(F60mDx96sDr~7+vQ|=Vr|Ql1}fV4tk!44ZN6ogbusoRB=!-mV+fjz4!~Jj)v1r z(oC2dOhWE=KxE+u&|l*pY0Mw7)2=k8|%8D z^VS$-KT=TN7gR*_jVvTHv=IgvOD9wX^PKf~;iQch%yoQv$K%$Y{s1`jHJOiC9#Aek zgTdxd{XV*4GRm~$%!O;gP?_hJd(Vj}&8lZm?@Dri&^ox*j>{yJx<)v0GX))y!2ZK(8ibyMz`z@ zJf67}%z6;vy_h`C(Dpww80hAqBEr~aptWlTssnH+>;ap>la<~S#v%!!mY_8gfi|eH#gy!5ME^E*fQ3~j#-~M>8_^!c3Fik- zjcA~Gq(W0u(wQV)w)vwy+5zFi$D45>u5rpA)vgWP;?%kRW(Al%o`V`OG?t90Vr8Mh z8qw2(HReZwb^nWjV+El<4w#(_;$TKmZiu!Dgu= zOB%WDYSn$5qEL^JM-~+D*_J1`+T5=OlT?>ZPg3PWf=&h+jN`@ppjH!dy3>H6({Iw?Kg*WbF7F0AnkZ7?4@^3u=qt4=u`s3JXw#XKJc6`>MG}R=Jos| zAOAG@%7WQ0Xz-6HAyxX+{g)5#zpk+N4!vlWaQGCTQHqDuOSgEf-f(n)X7d`df4vLf z7_q!=LIR6b!XOEq%dhZW5kqwpb?{hR>XJ z1ufiAxLzchrF)7C)sPgBF~3ShDq5PFXa=5=^=DwtYmv*cI#bM#IO*-%w~X~7(I;0q zbCv+&hIISyswI<4uvBN9UCR=*6ZF!4bTlvEy^cNpFM)3kTv1r;(V6wsV2%5!}?c^8{AI%^yu#EdtVXECpPv%Bpafj zlPg8J*%Qn3@cw?9fB66BgVd8FJ#ZTTC4c(x(vU5ZZn@N*HrgYLlj8Rm$^h8q{p{%O zN0scXr_R-G3Yj8JEpfI1g2CCO!opLe=_EJ`Foqqr2v0Kqg-8hG8ss@e3m6ex&uV6L zPTcNso#^mxvJN)?rc>uySA`5&Z|{$$4e)k`)J&F>q^VjzvZBd6ltN<1eCg3XAkX%q zyQ^6?6AOmZZCOHk;`Sq!p9eY!@<7m_%$Ha*f134P(1-ySf+p5^m=w(M&dyI@o>=FF z2+@%xQSeXZKJHo%*(1sT-T(3#QWA`%$~%aj+~zcJ+=sK=EUNho0sj8$3nDY5Ckd&Y ze5lNMhL9~ZjS%lII4NY%pe9s9{WgN-dTMeHnl3%7NTs3ETMFKxVf&Q+_?*C@QGt90 zq{4He6E9DSkVhoQ1pyKj<*8O9P?8mJ!U~asco3SJeZK9DI1##nV6hI8J|Zo}o=J?N zFROgKCr|c~>CYI_RZ9Akl8JdZNok-0)~3|xeRzU$m;8Y7>#f2lB4$;O0O>S9?rBoR%hah*qz?E$kE2}&MT3e z+IS5$#PUnr3t9Ip(_{S?PRYdnQM5W6$I)}@bpp_Y5O7_09=~n{^RsAQqEBu7!qLWE z*%2itjoD?=^U%hh=NQ}Lc&aVvnVpvApd+t$;Gg^9lvg_s*$mTUXyc@2{Tg1Qiu_jxP8pKDKk=%tZU+6SQ+XUVWE;K5 zjRnKfXnH)SHjejaxhkCv!s6E>BY(X~_OnUBOdI3e8WQ z?GZ_^nJybuyg*%gYU8dzmLLy*!7Cm6)W)A5>iGF+yI%0>7MXgxlPnQA_@g0hq;nTf zo=W>843IqkS)m%T)2e-~Y6*V;;WIpr&~M@=Rot zZ|(k?7y|YMnq*Hqd{f1*udj^3m|bwg(~(mQ5tyY|KfWY9~5UnXF4eA^$A-&j-jn=4Fibum@$C9`7xJR`CXS z6O`2`S6t8XI=QTDF67DU!b1yyRnI7sIjyR`M>a;uyFucVRX_A6Dj<}O5br$|LDbM3 zMG(v*mwS&xB8N)%Ss4n&#+n-Yfs!j~(w{QQHb=WoXQ~;$aZ<_89GVwqCInY=!d(A} zU3ok|@+4$o7H{TGx!-3Xta+iZqOWhRY01Qt9dgQxl^pH5JMjX(acary2kv-ILHWM~3W z=h}41Url^qd2Qt*OYA*CKE`)~7H7^9L7r2=MMWi=WU#Su?)OPjdSo5#+E(8o=9B{h z4*iU2gg!=*x1)^)`3Ymm&J6in$fD#M$pM(|Y8c#>;?(k=z_F^x$UYL2bU-%6{3Rw?kx0$27Mr$aXIx+9>b-F@{ravOhKP~URPyoSLk&)4Y4bz{nwK}os7a~fKwn8}~7!|&A`*sJ>v;QGYnT9$k z6gQpv+zk%_2IR=rH2z7wp+3@km&#L0j}95J7u}()$QcRnA|@Mco6~vtpBU=JJj=;- zUsSC_hd6B91JnEmL2oHff|Y-sT!eWkxC(TM#}04R^CUx!M~5?FXh;`_5>#%GE3X4FaX~X$iEl?UXW0f z*u+-pf?$QAWf?%@YfuMZC)A^o1eNU1wU7Ur)7fgc`_kRtE2-%0%G8rxUPAZ%+Bng$ zVeHzGnw3rXuHZFyDm5pj%Lljt?m_jHqT?e8(3eZPE6ysrLd2EfD)o?E46rbED8z)} zv?-Uo`$fFGV`#oMZ;I9$TB*yQS>=f}{tm`QQ@wrTN2_@I6_h|QQ_#TM9&5})%_>kjl7RV>*5Q8KDH#Q`BogR7&I*AZL@-IOU#$*QHA zate#;%wZ>N80aB(O(`1oR4YdY_5kq1RETyil$Q2ZK(h=j?OcXqEV63O$Shi8Kv6Ad zGa=8!OK#_Cq{4uZYFYhGe_+2;v0z~80(qu+sr!u~tr+JUbqC$J>T3jSa4GYj3%R8! zvG)DNh)*kDn%tDk)(%!L3fR1+==k9L|2TW^cq;h!f8179$tM&(Q?XeB$QD_}_Kji;<>FbATkqE0RUvn7OL?>C;429c3e{5wt z8e+&%Umoflvlq7ZwTN<$O`>2x@8R$H!vXryy1lUeVz$y{qs8A7QsSpZ3n#F)o8djx zk@ZF4Lt$d~e5)9Lxf;ie_8!z=P|?jP1nAMYzFAf3QNSo-u&g#Me3H^z~Wp(F_>a3F-s%HHLBFn zakmBbF0~}f%G#C9TFyelTtj@=OM7$E(v#4+FF~6eX=gx=^q5fixP1MHw3TukI==o6 zY&JIn*fF|`jK`3;55}jXFGWK37h&g<~YzZdmx-0A*R2 zeAB8GMV!OB9cTQQ1$FSnwut}wo%w#QvUo(Zb}P?ygS65VJ))w}U%GYz@9rAnY)05I zuFgbg7#w*cfD$aUNIQnKE0f^==xtCj%TiBwij}q3Q=AJ1zM5uibV?VZTcz)wTWzHSI)?m{_1_e|AuZn zUvz$IkF@VzA73*gxTRiZ{;p4iE~bgJ9xJTl7emxx6Q{21^?zN| z>#n8uQr_#s;giXM6F1B}2uDs=w&Y)b<^TCE-(!trV@{Not=fGro<(X`dT$rYP#sfn z(9K_(MR}9kHb7L^qBWvlblFzhY$NmDjS*#PCK_PpG)Vzq6Vfb!6p2p1n2 z2;;JHVN!6Ik3u9k+CH(rhC5k(L^E#GGve@R=M?4tSy%n+0yhfUOK5v(NbbjXpzz(jWDGLg27K4?ulWgn@?IWluQWcX6z z3^O&>^C3T`G**$b%%TZL*4U^ZN&OFL;C%R~LWKS6cMqI{-~DdkAHVxQ$LH@b43{MG z8YJfF7}6~;zpG=Bl1?@t@L^k8d~_6HaR+Els%nECJBM;F;lhYU?KH-p?5iNREzb+I z?yI0~GrTjTw`YK+?+aZlRXn3^@!ctpzk8P&Td}n30s>%-skDg1pxVp?yLkH7!btuq zyE9h5qH>POJJ{lEpEfPf7le^&3P{fedSRq=uGnN>S&fFhM>8VR{pGpeI!BxJ!q?Gg z#NjyZR3-iERQ+@C1pWyQSCTn52Rwc{);AWBnACm|zvjf2TP5!D zAKjFV#6MDrlwrbb9V+VknhiWkVtv0VJgmQSaDK)!%;sJGwt*(i+!6;l8f%kh=wMp_ zuD{iDU|9UbCnavDRFPA_#OSe3>X@F!SU(ZEj2as+C#64(!-Gurl`BN5Zq$rO+(B#5 z|NnW=9vtDtC5gG6U*xzue(&P{zT<-(r0AQLbi(&qc?k?kHDO~~LQj9NxrQ>7;|p(_ z<=NF!aIiga0b?i_7bjf>fs=tD#^D;y1f|Ok9p}g=?y-NG74`>F*76)tUSvD{d;U2h zHo-A3-2EsNAN8NpaG^NuKZjxnpezBMt~a}}c6}Po=!Dq5QDi{Lc+8qMZ5mDvkjmJL zP3Udb&!7|M*J!rKi1XJJZ8~>XSx@ovbsgj_+spLqih#xR(MZE_r0a1fesz$|o)-MS z-a)3IvA)Je$x`^-kwQlHuMD~KD6H(XAp4g(^ff9i-yJH!^y(q9JYdgE9uJp-&E)fn za*q$KHgzas^02YKuAvyWwVt-#>t_!sM!i;k&Vp&I>y0puhjW>=Z?8CavqoaM7FWz7 zl^;&WAJKK{ST_Q1Zpgd`DR4OdI(KBf0AfCw`~hO@znb0OR2uy8Ev$QAu_rUKuu3o% zGie3K#lvWF{vdBjW6Q`{zhW;`s@qt9ByQ=Wx5XrKISYQMsKR>zHn5bm=&*jP?vN*J z_`j~{%HA(jo|~%aK~v6bMV?Qz-l+2pL+{ZAW5G}x2aohdXHiEvFRk<% zm^?i%`1sQ?NP%(Q-%pP}TleXQzVF$EpA2ZiQ^)$`C5J~ZV0yi~L)y6Eva4@x!B&X1 z9?`)MmyZ#6bKpL$=D$Ae(S`i$(;i-aBkh}5va?pEI?taZRZs+htje_oQ+gFAhnw7V zA3Q03*mfu`PPa{XXSEN=>d86S<|`J$^orh~eDU zOMF@|x_Qw!Ln03*=S>|VG`-BF$v!P%+_%l6F35nt!BP5g{U)TS$6n)~1~nEh2hH>ITDF|YsY<4c6nQIc&;7~3E<3E%!ePF`&|zMn z4i%DJQEczHcsqog2wh=*CGOQRq}t7##|;qCHR@2uuQ}s2UUwhGo1 zHtymASnpRQ50=%s8XxS5g^u;S`vcBt^e9G~9OuNT)%16z(Cf2MHeepMj+0ex1Nv0!0wHQQC|eQxh%tbi zf|hi_al~LZSTS(`)y-gX3oC&w&&iq-$-ZiU&%$EUA1{|%8CoGq&8-)M{NKdoUG8wz zt}sopeVc_de9LD7aI_jBRleKy*B{ERdbqnB)^cVU+%7cHPf9NXtQrzrM zh!%U?7tmGt3^}m!!`2e(32`M{k<;yAikln`ul^F8Ef^h*YWjW7TPQh!rvZ1dyZ(3j zl;7EE1q;Sk75d85eY;0`ZJd7|&X7*~%mB_*4(u8YW*0uRtHXRsa@M*5Db37zO(Hbw zBb^DC0L0?povMkx5}O^h(guN%%Ac+tiyI?`Df87I2fgplpaE*Q1^*v_TpJguS_+7Z ze=^kNce?hsycI20Z%Ham5p(YQWG;r1_}XP+Hg8vUYwc&N%8LE?$L09)-);{CdxoXM zpx9~V!!p*P5cZ2p-xBTK!e>2l1RG+MnOi4zvrv%bY`Xh2%x4uG@)o{^Cd6iCOpm@?s!;XI z6A96;L){D?sR5K;<>4Im1kuVq*$;DrU(q605k%;|=Tk7Q5g#Ej5llPoUs`1?eBA+O zSbs3kSauKZgm%an7hk#?dtWHDU;9psj#pSMRCKTnpcGdY^sT=;+csz# z$MM0oF5ghX_Wov2sh{4{5}ReV?bC@>K8wpG``%}M(wl!p)sUcDFwu|m83af2&tXbM z+?|CF_nG(yvd>{$KR@4Uq`YK>gb)zv<1je<9ATI9|FDD)cY9j9_iMs<7B8S7W+V(6 zKZS^j3471b+*H#;U^G4aatX8G7Wf79PkMsYu8Tv^XteLn184Qb3|K}<^i>Shcp2+p zgLDaolkS!(R`wh|`xwOe5DDjT0=fC<;>{hJ-}J%XzcnS}3}AQ;pFcEN0&9{DGLbQ4vf z_|)Sx-CZyXguP72h`(s>HOW-Zae^aXG>(%sxd`l7v$7Mf&fd~c2KI9!(i?^()NrO) z`zM~cQrl;8T;jsGwo7+kQP7Z~@y*OP@jz76(9ap_5|y)KU2XY$T!-Qp30Joj>QG5u z#&h8~!oqX)rgzqbmW`V@Vb;CT=Pk-0-!zo7Rg>VmZg671M@Bf# z0%uV7!3v5zr{9P16a$8=AD~nzq{kYvV@hLUUhQnhgOm=^S5S#d&S^B)y)vql|D(A07szw} zYPKXc&k(7^e3~V$>-c0uGS~%{iG8kQxDkv&@SvLu*h1NR^La1YnySPaIo9sCdGObFb|KWM|i|%7%-Mw<(sbcfY zf@5ANlcIb<%LVB0i@Y2j2HAyiySkP3=$*WPiOi%l*d}A;dc2*T3$9y>{_fbjE_0o zk13f;iW8jzVo0OLX7UUT*!y>_fo3A{+h2jCrDv?Kj+E^!j-{m~WN=q+XhGmcDfCI5 zaB^?lJoJiEy@caFVhJ}Qq(9_P9LMpV3j>sd$5mcOzW@Y_;=*C0-7uhU{RC^bsl?KL zsnD&h{*lqqeIJYc$j_y|%vN^*e5I&6C<8un5CVgbZ+?<>JbPC#qC%2V8J!z8@A3vU zDkIu%<#@^34x1nR{@~8_>o(o&pznvG`y4N#p^bI^+`}hldDnQz3IfP?XX&txYz-Da zrzIqW(u{6?IYC!wgw7k26q=iPbX)Vg{B1c}3)4@h+^(NGrS$1#bm7RHOV%qBb@$z# zoTYVb+1a-Rx!TLKS%XX6u7}ee7M`CT;2S8ANi?tM``y7toxv^mxv=q=lfW% z{ZiB}T_Sei+n#1sJVwk+hKF@hdS^#C79%!mVdjVM+?bxhL$9~t({HZNwRhqpiN#2% z7uj=$)TFbGmG|^0f8e3jk2}~#$~ZLp{MyKx%kfg+VcF9iNX;uZu{c2|;){=*O(gs4 z2R)yb>m`VB{L!&UT`<;nur;bdVZUNL2QDKQ=olFI;^Yq(ykG#3M;&vr5_}%Pq4puC zY?cAJ4oDQ|#s|th^5RY;!WZqg0gaIm;em z$Ka~(p_k{HnwNUn%^SX(;~R-Q+DWM!^Wq(^G-PJm3ucDMh#9e-;E*IAk0OhI)F3a( zQYWLmAi{YVVs}mETaA&G?FVTFo!8k6NImM#iR6KZAJYUS6VsJy>b?qwa#0A)9`az` zu1)dlhv89XboRn#oWGr9j~j=SQnMCP#$c<&MA8j_Ot!nOS5^_wTj#$rhCUd$!ISVVQ0e8R)7vPTfB;h`^{ z{C<|GmY>kSQbaMhzGL0Cn7cruGS*}yK{8m%=h5Z4*A5b6_1R`Tz0Wjmf74gcF}^4u zU%Eozpt4Lvi0#UgRV2k&TqVt=fB&5088Xs=82#w0M4JV@Ey z{pHl8!)wDxg>=Uno?}LN!#rarGI8UE%YH6XJ4w#y#{Pkkcj4{#t zo>Z5I19o*+T@!ban)4PO^q}yP2c*Fz49DY?OTT{k@{}ixE7eA*3MvB z{H?gUxcDV_xSuiSzBoWu%YPt@J7CPP07nNb!<`BbISW2}gjkzl<}WTt#qa1X+Ojk3 z!*X~T903S|TB`<>SruP-L1j=V1AS+XH@k%@(?wW1b>3S3s$FLnKg3t(6dU|z38$IO z_k~vPIbM6)vAdXtmn*i-U*8|@E-;oVKXe8M@FqO3x&-5a9TMs3V&t$SwC$e#7#?Wb z7ziS;i7#7S7`P>FK|g;IL3^A&1=VG z1l*;kRy5{jkySgAoIS`rm^M?#G|mgoq1NzK0J80r}xgis)Gg2y7ZUn zTUVu!A?-8}GSuM_7hPT?BN#gkowfurw zd4^lKjdBs0)gPOTl#QV;^E&_Pf<`9Hw0;XvR#r}hXPz{ZWxRi^k+ONcs6N<4lrPTS zT^J}5u^SZm-jYMTjG3fTG?Zsu2LA9B6&3bw(`%k}uyA>FMj0Vp%Wu~uML>wlD;AJf z=)Wfr6JvT+shX4Vu*F7Bv3_`Hqw|*wg3r!*dW*R(P+MX9QxqGhSTdaFZjqp$csL@k znwsT@j4TFvs+6LXB!#>s@wlWS_}88IC#m2&G#_A%9qNchZ2K-Ma*SfENYP2YhaMF$ zw8~=F#$@WV!+8KBL2d<~#Aq)m;2%m?din|+{GzGl*M>cT`|dBtB~FMHGSCbd$3vbz zcHar2-z(ycyApl~nc(~841Nf%(Am$LcxbPa-@XXop;c+SpS@$mp1D%VkT^^kfk^tH zbrc0&O=R~M$ZahR&xQ$Bzi24B*FZJ#@nT}Lz3(2v^JkpZ{obr(pE-x0PD_)Otvn|$ zsJ=Oy$NG5T^6p$-;oF37rx$i%Xzju7`fTf9!1!@E&>!&r%Yk0?r8-68lG@W;v0Iat zAie#JBdaoItZ!);=}DxoJ6vSQd$@WwanM%?Lv_(F4Ie}2_lRqO%%Pcxnvj`bET+is z&(M3q4^iOE05fm)*&n2AiV(ZtE}*7yb>*pxnJLEMoPzu@Nu$@Rt4<#GOiWCYyxQ6< z7Fw#^mrZt~rK7SP#$Elspdi4>WfT!g#n@c28GL{1@ zXet(=ned--birX^u{Cy)Y=x(gT^|WqsP>q+PtvtUAUwnxP$&eYXWDlPVyAkKxK>A7 zzTW;i$7Tw(s_;5ni~aIX$rtv^pQP&fKQA!mF_1vg9dF=2JP3n-fy)EQ46DmBGJ^8A z^W+*Lio_hqb52Qg{7Kr- ztx;d!51TO>14Z+&4>7&_=#0dPj93$8Vat{mi+E_m+-K8n#CXW>(H(0HV==75iD?8_ zC%w#2W$zfv`{)$xpq{5^9h>ea`Sa@3>cr8D{zB*0}iRDfnb?H{4Qbbua z$9(%OXlrXbThCyc9wtzsw0XC79=u0mhaUM6Sn`+=qIbKtWa&bgjzjd#$jfrXLwac4 zRI6ga^3vp-I)RVX;wbLU#zVjT^4?6?&<{~gfSq{ljlf45q)1Q`ZY;QzL3+#uC}QO7 zhiKwN(x>F%p)2sPHklz!7x2(Jx$}}@U4udR!%3#`6bx_5(K_e#WgkC93@;)$ zd4iq7ROi)$_3riYXKWSB-y>xYmAvrV6FFj4tO7!ze0uvel1=cjTB2mMgxbCLbP~wf zWNNt9(|BVsCI?p}A@(}Mxi36qW*Lj|b$+oqq#D|;^2`2$VATyMOuVE;>w9&s{yy9L zy7!SsVBIJY?v6m}{6A2|(NY4&obCi$OfDvP8%<#g>l~TZ4It;njUbAs_R|xC@9zd+ zS;djeYH>me$QrnZUw&(*_{EX^S{_f9&;7FOJ9z7YdI^i7uCS<(bAEol>Nuu1kc!!F zGA6FV^GsMBfAz`M(MiZ@IrmMxy}aH!V4I@aBmx6JwlXntl82X8<~-j_z8S3UfpxY@}}qJPPQ_ww73v&@4c)M-@$#k-NRcuMn5{B zZDPXJMt&lfGN_YBtSk)=Cbk{YmDjhCe*llP9}hZEc%y387p|~*uirLj+K&nBX0f!i z)G{zQ9ezeM*WyEa`wn4pH~(sV?cAKr8EH=uT^*h6${Jl3*!7H(X$ko4ZSN_N*Yfk} zY_dYEcK6mn6JWJa?^m|*(9cDSw`ShZC>j?oTKd{FnS!Otk4Bx4z`(%F=hjnav*y*i zqn4Gk&F!w-4vx3S#}==$OrC*zm&c{okB1e~Gx`(xLy&e|`WnHa(w(XHiV|MPki_{@ zIZ2&6=N}_zs{U4aWu`ODi9eX793%1BWVz;db>*zQ*cd+9n{+$~#!uHB8BGcoy8`P_ z2j+|VZ)MZCbwJ2zu zJsli>_G6`ZBwuQtvVng?yAc;r{thcGsw8MFB8=+`Wfgp6j&1^^%K*gidGcC0*-%5c z`={sgj*fZJ=FGcW{@_8WHqzQM&gSuh8m3uunxoz?N}E=WRhGd6EdDAV1?d)t&=;x^ z!m_faZtf;0*DZX7_f+3Xbj~|enmK}(=QpWVc+YXNRPanMcdeh9xjDO|WRTg@y`IXs zvD2a)9080Yyu7@ry?Oei?f!wCQJ3VJ+$Db1pE_JnDAM!q>Cusdqg;RDla^tTd0=TB zwHj|N1Ch3t*8Pf~06ViMuK5QAlkhH-M%tLqU0r`*?E3u9y2?V&ErDGYDYtyr0HQjR zX|UPZ9~__=TF%JStj;?IBy z?)ds$J9)d8K<{Lwh{ZEJhh|;F!)lMUR&k5Z;-g+SPRQ=R$GVYJJW>nRW*=+@$804q z2SGL|HcQrz`77hZzhLVK`aPc*q=R_&`k%*rawD4=HMWx1Jt% z9+7Y!^_-=3WFaCMj{lqlBv$P(c38r8g?$Eb)?@M!%AH1Wvf@P%o&SH85D zjQ_9{4zl@h?~7u6SK!LDwx^3>f_M0%yP9XQbQqYO{-i~qOMb`BKoxT4hlHdgbtolY zQf8?qrsAwH0pF|O;M3CZ$L3uy<7&h&`dVM#i7j_l7|cm3w%gxcDY5S6Di0^+HjBZ5 z>;5;qE9YzZKe%j&sEd#1*D}m)hLO8iOk8Jy6Q}jm`Iu?2<@AeyPuGY5d?_i;}!c?LNs+_a9;3A=GzA2_?DN;&( z!`|fxtzTcRIw_{OK!J3WB-?wE_yNzY0o9kO?6tqrz?oftuh_Ze>2Vs0<#@LU`^`=8 z7M*f!G^z6ZCbi(cI5>6Z?Ro{_88v+~EXJ|RZU#(j#IZrD`u&gOOj6i{EuR~`H?4eB zv_ds=w}Jp>v^k6BX?zbq*)_U&P?9bTmI8ORGc}<&er>{~j=PV~0UWNriL?Tq%Xt6! z=I$|fVNE7|#SFrT3R^Oa02kNIJ5d+3?d(uWR;xy1Jk~6My*W0*mldlT-B@!Q0uuw41ewt&>gk7=!~MK6oe(^9&pdw} z|13rqZejrFkE$T!pJeXcrNe-G!3@Ch*QBdBhv{`Nt!$o3kO9_6*pF7PK1HRZoHerO*sLI>JR`rKi19h_+y&p1 z%teV$S1!%Buhs6ZT?O3Gv9bGb?hT4Wer}*BjfhJ~9!S0D{<5~io&0RDJIKJ7cAO>3H*#fJ=ujFqPSc1^v(#_uOwM8t za9OgkJ3Bk;K!IrPZ7v#1{)I)FJonVRH`N!K=nBTtjS2U4(;&5oLLL`Ykwm&ui+^{@ zm6t$zbbZU;y+4bI=0U#TiDpP`J;N}G(XWl+?Ic0c0q_%i8Bz)hFXmtiDU&980 zO^2|Jf;{rWQmXdC^CE^$XX^M5ujb@FnT(k;Xa?dyJZ7+#|8N9{Ph$m)gWJh>yk4}E zLxzVvyJLEE&7PMko=_wEH5^q~y_@^|aJ5;m8|+F(7L*1Y?*fZk93gn-a`2Sx-A3EF zo}A*x-riM2nCo{t0U;F%=NGWm^1BZ13JKNno9bu{k&eX}dWYYHaGL&N*Ub+xA{x;e zlD6(RTYSJJO(GT$UT ztk!SK7h^H1(T_BJ>~kX-N2n!S-Sp5m9aPdgZr;wrE3EmQOl{Ti{vrUT^padxC?1n& z6|3BcJ-3z?m41&?wVV-q$k-YutjIe3gqZw6SNbg(7U9ntf>rCM6ciM`xe$4+SRd~1 z$Smf4glchESgvc_Pw-8hqe{CGVE43-&N_aGHk&&&ln%|Ft%#dMm|m@@%xP+B>en95 zCv0Np=3t_n?>&F@WERv+tJlA`8A}l|U1Z!sN~l?kMt2mMKH2(23wYO_`9GGmkCr6h zKVTk0+h+v@1zAd6{Z&gS#6R(pQ)Q5OV0a;LBE*e2z81wY;kEvBbJBXAv_s7(W%Bp3 z1@0X4Brm;wO?w;}9rMXirF?)LkC6VYPXa!9+WL?lvj!rv4v$*O0|05xo@NhUt>=d& zAzgN$AjsQrz=&O&6Zc<@P#{;fxB}Ytt3p!s@MYM3tX+4*POM#r?D6I6S2BmZ6Tl=0 z{lg^a`mvPK^BbP`O<7CDf`Nu0!_0!>2H1;ra>g35C$B2#OzVVFSUBDl=bsjG7?XqU zm6+>H$2C2TWSK;n?J>e>fooO3D*axsb^Omv&gxatm4j0}8>Ylt`|FDWJ&Qv%kxdb2byIDsb_iVb^kORUyvOjc7j@=a{fI{~ zZDW0HiFUs-&-W7SUXcNixwi$f#Z0w?eJs;3A`Nf8wc^8wQuM$X;)9`QvKrgYfwCH7 zn5kqp)NJc$?0(g^(O9S}(^7o*Ty8C0|2|widn^F4x4DBB_S{4HQDPx-h>!n4>1KKc zmzLU(CY_?8;W>Bi8iC3)Dwdb-%s~Uq58Nus9Ucd3@)`c#l=Meajsh1y#h%i&^AsKYQ{YDSjUGhU9E#3t;9-DJ} ztPwg(J6RoYtCZ!tW1fb+B#*%B(vAAX_+sE7CeHRU=ZM{sb`HYFSVTmiScu2;Y@>zk zWnmi(|JjDq?JTCj=F=qA9}@*%{~GKMqGV#Gn)ABr(35=|JQ2+&>pBR@O0;my%}+Vg z-6cf{WU1Em8aG1BRICxcI|+vF{Zk)G2&RJN1WObSd}hZFSfQ94eMwwGh}-wI$FT1{ zD)b#xcxZx`?aPVKS~itHCPwSZ!3#NWM)#h5raH=;fioYUy-SB@N1g?pU{fa~p?Kj= z{_9({^LSv*#Dw|ag&FO`hE4zZ{zBk!cE8o@jd;|U4O%wNCAyEiOOk$EA$`#&d?8-c zeaT3155@?ja4)s}a1JVCh0?6tyH&JbDV9P}F(8~rJF^4cmNM^X9)ujU3pg>FefabF zW-R7lz#`EXohFA*M+Uy>5qZb_FDKHPSq1+1algF4JAENon_Ntn`$haq-nu*0Q9HHQ zfNAU)@Mw9uO$5k;hXw5>A$}L(Pte(UStO;?(RMO3oQ&P9F@}s{Mph1B>FWqYDSyHW z_C7B1-Z&l}fr!?v`w(=0wV5J*yjbW%uy*-}NxfUv4yXNy!j-sKm7HSlH_@x-SN7Ga z=X2Z81&4*&Z=Vm1!)5lX=rCazPuR=VH!3RdE(ZA3o#WPp}>=vF>ujCDe6rK5cR7v7-Ia^6SkAMx{0z4)qVO;lIap)>fI_}7i)i@PtHFC`p&aOv zFAGaYy8qDBX?W0o^OY^M2SV!?Wn3oG9k7GcGPCC+4zzAsG}mA6uzp2sSMLCq|6F{? zM<|eQx9Cwp|KN_qKfAT%+|ahV@HQzncDgKp1v}xI2Ia6x0ik09uFe?o-ZDn-rJN!o zO7$Z`Q~m66&y&yv3QDeI-NMulQJsC?gv}4}(|Wd93HZv}-zsJB&@J6v{ZV+xo!r+~ z4uBU*ODjx+R*o)@^DaJCNKw&LF>0*uidBa}+zP=ZwgI;auDJ@X9|FeQh+p^?pB!xqFS%X=l*pW={CbRDi_=rfu(tx(dW}%h z+uk>ClHj;Y0e8k#0@~5rnA>l+nPt4*4BToyEX>RddinBYcG&i%N#FAFa;Hw4f%kX6 zh^@6*K>KMOx+~f|)kbeEjyC~kxtm4&Uv{L|iz?MTjeBpCIrL-!LhtoJggPX;Uj*no zqZRi`b@uD8|@*6FhzI%hbO z;(98z#)S{ZAKgrw?AyF#j74VKrEr9u(C!tJZYzd%T6LW_}~A5;-gIoQ$# zAOMqia(WL5OMQfyBTi<(JUd*5cvTO_^u))Rwb)tY2^h&f?xx^LO|H)lEBYa#yUsN{ zGw$HTBYrs6Cx?HsmjFv9r|9ce>W{d5eVGyuy-!^b?G1JA6Ng_z=Mwh~uTZ$H-Ntvz z{z3bB@5BNrW-86n-{pfpVt8t2tlIlA;c2qH-4s85h*|FcHV;yj(&UJa}tL<(cCyRAk(#yhl>yd<6nm@(cbuu-c0X~8tHZxU!>j!aw#Dw zf4j)EDQDraqyFe@t?PyrkssnP+rkHe=ug|Z9kAzESRsjJcgPw@guZzPJPxl z`q>h9L$G=~6}w4-T-oh|*BJTsR@7d&{Zi4x(UmE9zgZ8b%mlofA-+K4NNLVBc!`~p zsxWeS3RkXI+F0D=kb34q!;lIMy&9#1r%)mhk)Xe*-HMLZov3JcE3La!;o@^f;zb=w za)LsHdydYm>hzm?RYxKK8Sl1~r$lbJP^mzshr1eE87|lfoe+nktC84Fx>NZA_vIv1 zT1AeIE_GMDtsg)G_A1XG4Ur4=0VyNjCk|kMFssC?5QP%mXx#oX3kfh2#vqL%;L(!3 znsqRe?CoJ>Y`KbC<17nXMFLE(;Z)1_6Js$~BuRwGAm8+md%;rq+cM4^gEgjAEtg0< zwJIg5d*^*UgYDj1#~@X;5BH?#(SOGB^dN0Y`fPi0AcBQ*hDiY7=+Ue2;UiBsqyCBH zlI{#9kIt1iz zn4u>wTh7MD5R|194$bn$(v%j2=(ZPr#1J`oy@!JwZMg5oVT~PW8yh4}q`3 z_zMr9XUwG(d^{xa`D7j`IIId^^-d7L%WYk8WgKuGUw4LF?pZ8L`Z67*7c(Fc#T!+J zn!Mo9HpuN|r$9;P>+`}UqUVkf4uMB~zjqQk@EJw<_|VJi`FAg`KTlt97nHvDZvg)f zN-x({DqD>)Jz$u*&M!2K}dS# z3bMD)fLbX3-a7T4{5lX+HFVG?tQP8h;@b-jq1HYrpu?GH9!?hVl^MivY z&d%0K`jADn5PxPo^gB2pCaWnkU0l% zS!G0XNRE>{Z01WF?-q+{J~753^$m)VY)p?&Uf2WrxnH0BQ+<>te+1I{#qP%Z1t$09 z5jE{B^$fKHvCdrGy!*qI9%~O)e|&qLoUDO+^6Q5wGP|H46FP6l7*OfTk1lEBlVVDr z)B&30Me~ zV6e~UKfC+ULMlTU>Z@y0A^jXT-0G*JZJo7&366(>9SZn#W<_2v3ICz3c^z%$tp=YfA>;zlPG)YvH+B7Fn z?-vgy*?v1L;1nh}5?u0)O7no@JV=R-Xz<7-0<1DMBz@wFE)J#WnOhe=%ymoXreaPS zYZ>Vlo0m1&|l=J=C zb}YSTrX{Xglt>isZNIj9rRZ#BpNL(fTGl=+k|`VU#^Be`~62XU8wS z|LgNQ2;8Lf?@7rYfq>Ni1_I<06*IN6K1kZeQAlB2uS+n~o~=R;T`}uNbtx$HXm*d4 zNp}Fg^5gaJt z1dV_A@FB#1+Iw&7b`f3@u5(#K{Mcpr+%+G|bDHp{2t-<2>y2Fbzp0{iGkcsyW(Ed5 zoR~AA#`#DA%~!sr#zu#dEB3VX^j#Ro$rqBH2Cq+kCjlt+pI33+ffUUyC9k!)_{lEM z_*GtD^oLVc?pR63CuC&rF^jkM2028JK&!On;RFPDja-B_RK{l#s}!JyP-8(P{Hcxl zOm$jRL`2ic$!Vtgq=I5nT->dNRMAJj%p$3qnwn;IrjxVUWq)Juv5Cm}%hBQCYV5;B z_(`%=1dEgoe44=WutBTZlX#G6OfQ9Ow??*>|FWHFN>f zr(%78<38WPnLKvx{?Yp8{+IP7L9+)o>!F97f{oEGQ0@Bg3Kq*p7jkFZt9iXwo;JPo zznkkA-M?Gnd@j>eimWDN616Bu>-ldy{1AHCSX$_LzM|KA2+j2CQ<;pHFXIa1JzQ5b z)w3BN8PfB*wA3~CbKn8A=kvYEK~JS;k0X)z>riX3d&ewm z8ZtXiGgadzBnE*1liEVozU^IW@Vor?8Ki3K$0_5I*T`4Ny{ zq-s%k#3FayA?LFHE9bTuKXG7>lku*2xD79%sD&{Ix-Isk1|_N-?)KL-4eFbEN9*O^ z=}aX}y6#^~J2v{+_QX_IF&*N^&I7ZwyY?K!o*?jq_GW^zigI{GnzS5oR~PV)AEDW) zy0^JR?jW*&OqYAo`25o-B6k1EVl5g-_9>K?My0IA3;)IdYV==QYccp>Dy7vu= z^wWw|!>k~`n-;ioC9ZnsC)4+_1+L}64>>{hCO@i;w!bQv>|OUKu;j(5iO3vmp_wim zxN!+;rW2pIK?iA;{!6 zgwmn2Ni(JgweJbZKgzvpzsw4k`U}~-x5uBYUP2>>mBq0R0a!QnXN~R*tFn*d#O%(5 zvqM36!}GQKUqZ_$9t&F!OnQst$WazP52k=cbD&(|D$bNkbD zVrQp4aaVUY&qv%@^m+rjfcdS%fjU{@QxF6(w>}6{`3&u58QXd)Hhk%bvm$Fi4H_DL zbhEP!s+IBK#WiB`#pfe%lv9?~*%G<@XkF-qpa#s>mnQav)V%DMXhvh7)o*bD6xznM z5&!BXo@8LtU^w1@syhw34C27hQPW*B5Z_9fdCKVhN&MzdDWBC<3Ehd~6A28OhVSG)Tk|4rE7RFVmYG|z z`yo&-TT2q5q~x;5BPGCCTul5k1B2|yZfQH{hDpuDCtF12W_<=QS~ipd+m5Dto{Y;- z|F?HQ67--UCVP_!4U##P(f#+)xe-uCsogmN!nL>?IqafTg^y!_*i3op(F={Mzz5ZM z(3rbwEFJ!3j6Q&#jxL%2`^g@mAsMI3#-X*Dc;zWn*t@Qag_e|Ij+NY(ezcq;z=md) z))ZtIMx~wtj07pi-24gAHE6wquy%S`<#6Q3vI?&Iu5L$!R+gVz82(6pR4al&!)3hj zDn1ejq;ABuKWmt0atAj~NXx@Q#}0A0s=sPl7Had+JMzua+Z ztny5((l>^Tc?MHvxIk-}?{ZU~M0jbdg6e8d6aY=l51}fMs&;d3JeGs_`ZDM5#@6?r zOR%RYm+yTgx*BC+Vev)$Vv?jQ?^w|#JX!}mDDa*+&n7I3lRL~~oN3DFxNF^HaS8}4iU-qQI5I68Y<0ca~Pfa7nh{{XK9*{Ng2P%tGN`HX?jrl?X zY_6?MZOkcRMxv>9x@s{B2bGX7tt55?=*{5e)(K0yN9NT86sy7=?Pp~P4{&rogSfis zc7oTLw;)W>Q2wKTcx&Zk_B6RZuJ=mGCR6#nQ%_H?3$!H<+LNS<4?*L2!DMXuQ-RTB zL*%oe7#)svTr@}){*S^z>4jSUyFcPR?z!9aXH@yD)Kd@C@*{9vQDPa+Ud}A}xi9Rw zdA|;p^Z}vGvo->QL2$eMtv4X-`F{|$MS>Kpt_k@)G>VQ-@97c~fg)=OnG%jX-v3Do zxmr~VOb~RTiskze({@h!42Y7TW$4s;`hDZ82n1b;t{**oS~CY*Ad?u+?&|ungh>#whhoJp+@ zIT3INsNFQMpC2r>W$*@_Qv_|uJ})CoCbz|0Py&XE9fd#(h?p=(bSdEbAp~CDF#+zy z>01IZw5e68_%-m5)=|UM(D1)OX2f&>+|igitEPo{fwEd_F8KK23&RT=V{WJt_z z$xn|Pu7uGSFQ#hmsc)A^)$%9b*Xlby79(Ws&B_QIgw8)4L|HjV9@4kBAMKpy;RzY> zT2m`;oi~I=SV8~sg2KXB@|}hVmbJkX;hJYp0;`BCcc18l_#c~{tiB?oYo3b%4KIRI zW+@Pf()AOR+jxCuLndAKmTE z6CSw@T|aIIVQ@BC_CKF9Y%OX%uQ>aLo8rMIaaR1%l~=L-kr81%B8W2N@%Txy9YX7~ zlDpm1xp$mjFZ}Y$>IWg{E1|v~n9aIrWq%vAI@%3=nSUbf_r9BAf0rRNk#AkM;T7y3 z!NOK;>F5#9<}aO>X>mEIl^LCzYbbtfbJf8A?OWzJ&`z8ji)l|K?zqgsF&xF)ne>gr zZ~T3pKNQ$awqSZPk$Il5oB$aSQsj?t{p2_g4_6(3bd|y^zqaGujgasQ>63c=fDP&i z=A$miXrxcZY+v=C)H5^OEfz0qz4WURE{OsFLa)w?FJw+(PfZ7QIjX#603yfFKC|Lv z1j0l?@2?@4rv!BwAgVc7!~b`u=Wht}j0V#ykRfd`@w-X9~@C!=|FLD3O%L-0zB_(G3XAD2FZ@(q>mgAKcA3IkB>hS zfB7B>ykPsKl*T5-ubylG-iVidm{sIW2Z!G4V!iQQVfsle4cSiRW(v|aZy680{e55Pz zt?;vLTk$K%9r!*c@fKw_zI-#zd|p&E+{wvPtH{A@7*q^9h;!0 z*vz{wS~@xf0Jx%w@EGaq=xEO0oafIs(uM#;Pxm_Q^{fk~G1NhWPn4f=!@_)+`9dwf zcpQpMFM%w72{NwF&TrG^q1WEMf_J# zb4>OX7~|Lo^9EFyPj@m&hJ6~m>O&EVxh;2;RK?AoY0(8-#R0U1hvPvVsVxcOkz5){ zst*bGRvOr}1y}C5!>q6i)YRRVy&Tb+d?HB%P|;}o=ZXg7hq&$7*|QjvL`$7x>O9R6 z3_AI>wY8j37PQ!B$7Ta2VKmd6y7u=iPMy;7PZluw1d-Gb&YxEKFbN0{^kOWdA^61; zTi=6-TCSeWf^|Y(aTxO>!Z1z@R(pSh{QAz16RN6Wc}v9?Z%x#5PKBv3ZwzRr$yF#t zH%`YtQ)s#XT__PZR?#BuR2mF4tJ(&$2O=UuxJW|gY=Ei?tX}$B;*S7D4m?4zRFTpq zPrSN&B}4h@&x)9P=G+vVwD0{9v*EaoVXlvMdS-^CKXiJs4FTJH*P$HLX@&+MOH|Xl~GnGd(TR;a*T{@QdyzQ3T5v@ zGS0Cn60)<8k&#WA*}v1NJo-)UpkI^4i3Mkv8zI)URDQ<8OGM`)BiO)69~*9vObExHReN zE8no}zU{mpYV)t9-jYLvVl8*yjrS}{oT*0;h3uOj{Df}4?3z%6jm#^XE!*v=+<@+Y zUyBuZ6zji@CH~dlQotAVldt!x^%$ z#C6MK(R^YzgwjgB!Wp!xg1k8YmsJfYaWPjAp@4Nx9vQ4<$0$aU@)1S!@7c1cWcp_|3m=Zm}a+?coJBjd$g3t{?(& z^{J86S(?F?6Lle4K|qg!oKu*RD@)9HM0%1ZOl|U$88}OV>Le*Z1!<8L8GdO`otXX9jg!dcDY@H^$LX^-cb}4X#;u^3QX#* z0APPMStEjsp#$PfrvTB;@>RBz2QrWwECE1?rKp{A2BAyDb4hXn`(}lt8?!|A&1|Q= z808-s?gJfbH8@?+z`Wv+|6?{Ck-O^zR)znA@oa$_%+%!i6vuE4`o&p=&Yb)z?u}PM zHq@0cqQ{YeA_NUN6TyWXRH|=qbDbEM8 zPnKs-huy|>xP5F(v+7Fk03f5AsBW4M9<}3(x@8ii1WVkN@Fz9b-$FlSDU1$7BI7jpGTWZltKCTKrQdHC3IhaT&(xf)zU45uN zf1b8}fa4ZpW0Kt&V%go*^o0$-)=ZN{8QyUZ7d7$rA$r=D0P|EmK}718TT2_77O(tQ zPR+Z*r|LycxGlOc!@c0%;JwYU6}A`Pft)(}p11g#w3O@Z0HwX*B2g66@&h}k4PC#Y zA}5Xpbi&?Z*q%4{ahA8zDR?M1?VAS|PX2phyYapPv&ni&$q)U77AHTl8CCcho|S)Q zUt<6~^~Fj^2Xth)@;K~(X#s}k4@}E&Pc0fd{4>hYq0Bo;g7IqnJL|=f>S~}!-MY?E zRH~sh{P4Vp+OcnRJNI|0_wlf48kQ7h1PI9Tq#Ky%dYylm=w+Y9M&FA=XuT0cC_yJ49o^0z_Dn>-)}vUOLLQ)?t-440n)7r@3DpcOQ`*4oy_ z;j(OY9GV9AO4xf#H;FL6JWe9V0BQ{dn)L^8wiR1H$gVp~|3LD;t_**y?XMr-DEr1_ z0PEtPfkD}YR}Ab%dmtu*qiiz9@NPADfrBM?S2asR1KQP*zPR+yees|eHd-K$p;*-} z-_(*q0g=65pw@ZYf#GL&RY_-hYnLMQcJJ=(yN~Z6_m~e0h^*ca{HvT8`QA!yBam5d zb#gNqQ~rS_N6cwjdSOsFp(|d*;Sr)XFetW;E;m*qCiK*(AxH7*SNU=CKbO80ef5SF>LKou;i#l|O1L%q0e#o}aL3AHz6BB7539?rTl ztZI>~mKTpw0I`ATcH_@+z()tw5Pnx@Y$a4tt)ZKU@0>rFu!n=A0cx@90pwJKmuc58 zYq3g5+!R5r#jx(TCX|zHr^wtQVPmUdiDzFHVgAb1|9o+Fef4t)>c_9+2OI+=fkp7n3y5r%W z^H`xE#S;z|Xn0!JvfeTEejs(6#SijQS~xQ(NRv%vav;L{9P zvvRusuGuTDRUZr*!dWs9`RUg{Prv7O_bb3|hfJhR1(`D4EvVT#lbRn~Dw4)qA_1IP z8>A8;=GSbNhR*;2sMbI;9ZUiB*kQ#=@)sS&Jd+cvQ8bCJG}P`3A)jifoRll%lK&>In7=PtmB0A~NoA#Eq&u1UL? zR$!q*F7V?^;)9OUBB)nqvSY7yc0PgPbSs4Lb6fQckXXlo?@_yT@VLp+D2B;3({EUn zjMk0zAf_i^Hgm5`*N4z_K@#CKINPK5=i7Av79XT{bjCDfw9gPYBj zpVavzAZy(+^!-a(tRgh^Hw~r-07lEL`1e|x!xfnInC>mp%;ZMDd^tUE_3PK}?hYWh zrA}?IhUNkoH&xx-+#IE2Q(z4C;|*{y}yj%wyzxiIVLe0u`uCs#vY1Q#f- ze8l(|$uHk=7!1*veZ3W|6_ij89tS)DY<(K&YZ2o+hYOP~4eeP3h@J5{`+pr|y`{=3 zDlx(wWhKYarqw1N3_JTmUf^}CVTqw z+|Adr%CUU5J+1ju;3Iaz1_{}mQkC5MW%e4d_wL?a@z;Ho^FbVM5@BF+tNK)hI#5Mj zim1MKwWR|K>mYcUbQolC;}c=p@2|%ih+uq^hWxU>T{$<3EnzXn&bz{VWj8AGTW| zo@V(N;0a%?TT&Vt0OQ=j!^d&|m=S)nb(W;+$N`K-IAXNzEL$gh_aeOgj)nQwqVYljk#capKug|&R`VSa z1xap(F~;9;{WfIk(c}GznixBFb0r#j@#(Xm8q`b zN)Kb#9~uupPSgbkN=}bw48nYt)Z3ePz5@szlw`>lzxX2I9XA1^T_O;LIy%e4sl@`H~UV8MdYK^ zY~*8{lA~1zX3l&TRjJUmo-$a2E&@FkcA@%KOMW{M$|1W>X6)K3ss%pz5k9#ik2v$S z+e9+vK@sQ-cJh!Rk*Z_3U=-wtoe!q3y1l%z!hmRLipGqeM|KsSzzqO^k6$b5TyhKt z5gMcu)T26Aj6G{vXWs$@t?K>{a-37W+{82aq3PZ2kDpQdt^9s8Di1r%>w~G5Rf@B- zvyXe2ix^qJHWJNAvHud^(7AijL1$$LOExZZda(`ue!6RlX!41vFtdiR=sdj&h79?N@i1{l zs}qqC5fgJ$ZC-qEza#-7B#Sb2>X7TS4S9Qis4SY+J3BM;xo!N@=Urru{S|J7H)=WG z1`@k`8(VVV`#ZeDHcZH(m2tK!Biys~`5~Kjo`X!7 zKDq!VM?}@}uIRw1VvrUmkMT3K$60I0E>MgA`Z+}chwbcr7N#&m7xvuEX5m*C+I_Hk zBB+HvtDEf?!Xlm@=htLk4;YVWaP>P-^fR+l>=9Lc3?t?L(ND994Wrovx69a6^bqf!PkW3-kI{Aqpf4cC%1wch_YE~F(~bpON3 zAw=7e=zDIS9Mrb5f7OfuUN^x|_mi>2rZ?>3#fxl#_2k;~m+O6G3hYVh5cz=2)FuCT zRC}q2zcGvF4?F|_xGV*X)hd`Cbx`|1!+lbrG7w*q2Ro%`zh6F(GHMPE0?tdrL*J^3 zAtU6@2Jh5|@t;^Dr2GvKjD5f|W$Oywe~~8Pm@=Mtfm<;9iZ2VQ0N$r_%gf6Xi}S2H zkkf zu(r{jemJdk&uS;Lzb-`l@S#xJvs>8nD0=4Ihs$>DPRJ25lzH${3v}g{LEr&X1oRHI z0Gei_708n+`{fBby_3I{>2}$~4ugRw&Q3#^`*Q^>6rfu$#Qu1lLWqo@GE^w{xcavo zfJZbD7hH!1`f0FVD4spfgV_sV?551gW!$N<7oLC32eXWKV_GV(GG_YP|1jAVZA|_Km?0MiW5-5z%AMQ9@Hl5S zA@G5{x3R=-WD$4j>)^b*^IErVv)M#7S(0e1GJj>%y)Q3M=O9O0!<_~%?~!+LgyLGF zu?j3+Q78yy)_3l@DSYDNBF=7ozW@DVi||NltciQ08%=OXNJ=!1Zj+cw(!>4T4PhI* z%{nG*y;uCz^HW~5tRCN<(8T9Vlswo6I4zRd``2y#{q2!`Nh~5>cYLKxMKzD#Kr>5w z87Sy$-@cncQbQAI2j~QQ^NfE-K=dsd9iH|a-TY4w(7-qK1I>I&++7REzOjEL z!N_@~eSp^MZ70ru^W{+831Z#fZrBy6UcgB0{TjdIz4Op5aObs1_i38) z6dgA=Q6%K&ee0&*Y2m%xu{*94Wq<1?oK>ZEFCl^g$HC2SkT8-88u6x()4WWj@!LO3 z1QC+5y7T#InY%PD$ILd~#Y`6Wnxw3>imU3Z5I)$mZDVJvMRyt*6x|2G-~?H=m&o`t zLB>%Xb@dlW*cUBsjI@L71r#v*Pj5kcOiFYfsL@{WbYrqm5s$}*1AlFkgHQFoWbJ5A zc#co%z-xmwypLD#eg0!p9sSK6H^&H@W`;9+pZF!uOteLZBS~X$zUG|Hh842Du%_Do zeH~+*S;Z$9{#yhqXwmqg;1@wKy1Dd6g7aC0Fft`l2U7Njl9Z5Vn;0P{=VZOFIAwhw zqX8QheX6x?2=reeS^w(4ychSzrS|;aJRCcU35}P}_u5`Z4Vw7uI=cf`FjVqH$s8P# zMjK|&gH3t-HNY6W{6jZa@2aOtk!ET*gD@(-Ss8I^O)vTEm*-AZLr}?yAAT;T_CK(&w*i^`C8#53mTSW3=kw~-UR65H^@M(Jd#gGh z_gdKQ&BqQ%8ZlOQCFsl+y1=M0N5RukdQX>My`G#W7bKT*(am7 zb~T_5Fm>dbL745_{{Vt%Hw@kq5n(4IZzzcuv)l8W%VKigtsc5=B&V7E>XkpJ6Es_T zLIM2ibI8e^NzTP|s0hcWch(2YOuQK%E=y`5hMEKr!7&JxdPev!#^abE?$QTy&Q7p% za5T$5jg{P<7X)3@o?N->Qp|;u{)WcoE@|LL=tNrj1aVgvvO022vZGJ#eCu69Z13LQ zRabUmSm`sKJPQp?gYdt`-l1iovIo76F5eD9>1I09cwGgZmK}#{0meBMSRv`w%!~QV zx3jZ=8F6u%S`CONdO@0>Wp5x)RDylXhSlzjrG^_LUaFhIbNr%drkMpH1bCn?gBQB8 zuH}r=>{rDy#g7g-uYd@6w{p^7RtW!s2?VW}i-}Wsmb8~MiKC8IA|O7U(4dQbh~OoM z1NQ=`igWCmJD}z#fFug&fq1(G_C@^-&01MxcQr{Fh4){wuoo$4Atx4(> zJ%83OAE(p%<`gtvV#i-ggeoZShs-VBgrZ-xfVIoaZ`Ci^SRBgF%Tp_qR{a1XEe| z=1G9{y(x~tJ}g=9zQC1_iJotoFIZOoI*2dO(mEwTqpqvV->UxFnS}7yGo23lR0TqtPm61{_~O28u5TUbj+Pn5QX@EM8!ET=3&Q3UL(rG z(No@t{nsXgT8NCmfnJ)=jalsc$|m+ z6H&u?Jeedl$fGi!&WdcvA0rr<9~To@$H%*^~8B_I%J zL3mNHFcU04PCrKR21*}fOodqr$oZwFvi;PT3=CtIP-3_|n$D&PGS(v*CK6Ne5AFu@ zy5z~K=l>P(V4H4Yw|C`R8`Z&^12Y~Z#{L}}`s$nP1AG1Nbgh9)Ts$A{R3uHSJ316wn@9rba9Krgyt1%zKiyoeHA zLY`c;v_DuewQ6fNgh_E@XGPZ^&}rw^KT4J=1fdK|@z+%VnR9dgMVPir$BUdR-Pb5- zwykHtB_AvOV*8D(L_JgA{7w`%&JBrG{Xoi3Mu)*Onfs>Yudc36`C&}!(aKcY#;QhI z4sCgeLxI13Yl42jw~qnM*+4323`e)p#P01b`812U-s%D9#j-VC^t~5c%j6AwQw|B3 zAwNT0YZiIGXo#|m41t`yeA5D*;JxdCA#WdF!8)_WQiC=t86QRM=tw2Gy5RBjFouMr z1WZwxg)j)1Xke!YL4Y37*0>BOVutIcg0cVBQjtlR_R7Tf5F z@I9x;+&wI$5996W5K8M6Tyy`lK;b}9hzPNm{<7Bs7^JM!6qn|i9zJ>! zBfsjMN&eZ9J|rp+JkBJZ3SXZE;)5ujKmxj8X#1_*7fYwkbe^L>s^SOc-2Ifxwgc@G zjgeN6G+VpyY~VIed+7s|5TNhP5+T@b*(7PKG- zQHOFjJUlUgu9b^dnoaj2Kuh1fg)l>_0M)m24mSCyJ;gBc|#IxLO9{cHFZ|1ZVFPM~OfW4fo=h9!-te_E4E}_3~%NvyzE>f$JfOHp4uil-!jh>s`mf zmA0B=x*P1HS6t;1Ip=lzc2ZdfPb53%I&#abnL*0TfBu`pb< zkJRocu~g#DPLA;6;p31ovXLnlLd`7GH1z{9+<{%|^Z0r&kC&gJOaM9hu;UPXNs+_2 zeDC5qF=pTbw)jOYuMq}Iq}}yF+unv^BvU+zi{!O4lBt&U_!VeY?>V{1gU?Uv17u0? zJ}^*bgMV6s16XGX@`Wy9ogt%I=6yzLDlkUTwdf(>n=SKfh5=Easa<%#kp3>&ZJfM@YhX)8ZNKBIfm`DqI zWeZlpxm+9kW}my;J%JYX%6WFqBEij`{lMKNZ^;ONnq~`ZF|_t9NZKoOluvW2YBUjA zM#!qOZW87C?E@iV_K;Zns>!yf-%IT<7hwxIMu~8TWVbADiaSmOI<^CLGF)8#&~pR| ze)sWE;jbk&36*sYOAt4l1hkJ35rCS_1cMUDQ3BY-A--Naw6+vqXYDVltG(Pwo*aFz?;DtX^&I9&~*i$jQeRMdb zg&29RA*QT{=TBbv0v*_gQy1{dfvrxpOEZrupSWb)H|L!qifmf}@XWKkB+@ou2XE+8V(fixXF@UYA8 z(jwfMpu6&^jPV{vB21pq)oj_JCUFqB3ShN69JF0=4{i6wzy@6-2xj%o!WKauYr>8k0*|CE&6fYVV6N`rLi*esWYlOP79yH3<;+!KYlvq zB6(_Xy%P3*lYzCgQ>-=x%gFB_4o zah;tSYfLsHXOC7*jZsI($AcSifz*47b^ZC0D%VAyr}%`|v>}1EI7uH&q`fJe?o`Ju z2p#nLS`hW@Y`1{{oN$o$Iof05a{MYB$s*%{GAfed<3}w0l6ArC->r%#+Z_ARK{`%>JE__Z z;jtCk4O^TCCpZBBQGYtY;dvUMZ8WzMZ_E*r6~ZWq-)j++zTxI+WOgm$im_ov&!of6 za*l#yG#r%W`(}xMpEkPobANe;5PC{tz0VAp#KP;}2VRKDE2b&($6kYlNMdsWf+7<; z`gCh%utFZS?vwV^+Y0v=PTaGwh{R z06Q!5acysH%;jsW^O_RbD`SQ`y{q?juWM-W8CKm$%e-_#@QvB$jUdnbgExuO+S0AD zj>D(ym0RQB<$6AMwUqDFbJILh^;K@xye}zFVSmRq9qjK-4T)e31oAwB(eP4Pz`lG7 zV2d=~YXZqa_c7P34VW0!4na}h?P%_YUxYGWUy2pXZA<`=^vv=Dr>HMZ1Rr;sCJ$2K zpk5NtR#ts)QggvWEx<>_Wv=Ju5a%EkFU;_E6J6&blUVS$j>JHTa}IL@df6m8I;vwv zlq2g$UE1?4x*TzE?|R?GLv6AU7@ySJJ3EMxuXtpLoWzK=mCg1oHWUeSVtZhO?i znrl#D`E&q7yyVKF707q+aKI({$A<&XG?ZGx`%jmOOe&7Rt%hF2MhfFrXH)b)0yqyN=-or8bpV!eR z@<(Hy^?|lPf#S*!Uz;CwH}{}EhRB~JPm%9BxnB&#g#Bj6UkPY1ll zlRgp`QZ2kq$rnpho04FXNz8s?qKd4}s1-<4y4EYuF2QiwTGqDTVGav~H;!%^l}VF~ zkB%3~K=*Ca0M%Uama>!hBg3_)-5K;PHU|7AhuzgORG4Om zE6dB&OJK2{P`mW&9GmtXX#Op8Aa~oMO^H-_=IfVnC-$Y_2iiu}_^?uc{dc84J*h_7 zn??52Y#fdA-d1gHlI!D(bDL4+(oB7~YRvma=ST%{Hkl zE97!6{E?OMCV8eSqrB%f9?9cmUq{>>dz;HOXtfDacW@P4Ri^GChm$FSe>wr=sJ!}m z;)ie~%2m%@AiOZ*{^_N|_B?lIt__?R)w%xuNyW(;^z$@QD}_lolXVP1t+)33(dA5Z zRGtG||7 zK^3*1rJqwk{~QWZ47GPX&^+yKJpmiMcJad4V+r z$&)Fz?mqL1;p9s_6T-!HEu>ql-rrs7c5Ci($@Ryt`3P+%2Q|oCocy4qjNYDhhY}TiK^{Lj~nNk^+RUcYamHY8XQaE17bqsBGE?A zmPRhX3i&JOGFtK&NnzRh5ujD=z59-6^{@;xGT8%}C~lCk%~2|U8;Du3cYk6CIs_~U5k{&8 zJ-SMQfpuz6MTYW$AG_9hut%%c)eU9NEtpegpOA9XDlme<+&7hst3353++IF^K00td zQX3ReZ{NRiMb|yDJ!lZr;PC%bgTP_WlVp8HXbYvObX}>)1bbvn+FL|SlReLrq5*xR zkzPv>A0?{E{(WNNaIqaWI)8$yV@99jdMC#x8{p1&KLb)FMf7ir72Tk6C{NOBs~wu@ zEZuyQ*$U0lr&F$uCI*%6zinLB-Q0%^-l|!mI@xo@8DUZ7)$m?k>cie9fN+f&a+-|=9{U_C&4EG>VI~mKuDAIsMSl)6 zY}j;Hi`PRg?UkhzQSCb}Td3Dp+};o0x@>EFa6!d+v&Ij_#GQi(Z0=&4-qzBlIU7L! zD`Ae$Dpc@6k(rA<-_F;dB?0@G;{T|M0OR(Ur@v$=%_Qce zmgTOg$)u9p*x1NMalT2&FFqW`rKD?cZJ~}DCP_ae0hnOOt^d-4MT50|(tM%$1y#Qi zPk$9=J!*Sp)YqhG?Zl%azNn8`leqGn?NX3C$U1w9L0)*aLI&x{oVVVz^UZ0GmRmJbchB%x7pxi%f-i+4)Kf!tkoT= z@H?gl*S^dDxb_KglnvcmBUU%GHM0%)4Gw!e*T}%f7Bi3P98Noi%~D|kJ-NjfF_fsd z+vYU8nBe}Y=;%)@74R!;a=lxGFbbaq=bN`S!|#vKAHvLwyG*-za;ZTSFM}zuU2O-% z;_$$wR)|!Kg4k~O^3(mG@}exeM(b-xRd?atLn_?B=MkP#qBEadk3i+q0GT`bmB5Eu zk%1pMdG0kb&q~w9!#4NRs=JHJWso>WT=C=7TC4RZj=pIIXHz9PQRNy!l7zpfg^_E` znK%>zv@726gtL1*LYL%-eNF^pOho}HRy#%iW)p3Ud62xAKltu4%KVClvNSCq7m789 z5ffiof!)WS4nsVf28?4c^^a?8uM zFhdJq<(L;r;%_Glh@YSDI}LloDIjEfJuY~hT0D^P_SEwsdtB$9+x79Ndqe%FIfQi? zF+DcnG)s69b;uSB?%T8ihukwyMp?TK<5lV*c=_AWhOSDgswrz@*m|ymT{fjGYS*+0 zZ3uE>e9aWFV75_ifNk4AURm2NmUh9+vFqI%CoeIuX?QU@wIK5Y)3L{TInJHai00Ow zCK;^MIq&H3m^39gxX%?bME)mkWL$&(B5;gLl&9al_6!b+=@ZnK9)C|J#6{%29dQd= z)=fD2jdQ*n{8e)e5V7)ay9T()QeV>4&op0B+-nRBseJTH>>+7b3GYav=4ec+(v_!L zL1h7nFgAm#1}#zcvEFOjicF8wURi@Z528DVSOQa1ttUr&Ab6*&p3iOs4q}l+P6(&3I4gU~1A(2k z96;9lHyQ+R*x#kb5IFk)fNd%(eX(}OYT6GUqvlW;jPa~2amG7e=Dd^_?{K(C8hTGkiyS%;%j3qkr!wkciSf9&&H48^ zC`0R|U-2?HPay6>r=JMv8P-gZOukpg2YQzhN)H zya@NPAP%Fof?NCt=Z(q#IB)Q9O|cwJkwg9K7jv%fkph!NfnV{&IUJvgYz zP%T;qJwNmAIzCDWbwj*_^k6Bhq0VJd78cHY{&u#=W`l3&+gR1^>Lr!vz7+8cr7vk~ z2WK@apjOA|uUt1z*Z;zLBG{XdNPv^0-i3rn^fAXN^ol6)x7x(%y z^ho6{9k)}JzVZr-zjMs4TPH&?iOUayo4Z$Bh&}ofV39<+1*)AA#N3Dx7(J>vbHZ!J|e=4_X3v7bvbL%!tw)7!$`oHh2 zQDja|GTe3J9~ZisPN3RaNgPv9+hGe%^R$2=F^AlnXFMaEOu-_0qugbohly`-P!&#Q z<{=MGi+Jbx=l;pMKr&ljdf0wza;GTpcS-e^uj3Fg~4K7^4!7xAS$Tivf_V!z(W+j!fC%B zZu-Nh{Me)0P*5qY!48eQgk+}M*KVBrj>yZwB%1Bzy_&-EB2`VcAQlWPxhzoj_k=;% zjLll?^nbQx3c#ELP?LUgAN{N7Fho7+UNK(k@rC8$+>7R;km<@%Ys;EF%B^e zb}~EV?c*QY!5AWQEj9pZVV!@W4_H*pZUn_o$76KA{k?6R>}W6EJ%UUa%Z~I* zmxPoa43FFxc;b|xPq^pA!sb4e4l74k@mW3q`bNu2co1b6@i9Ue30EDW0(+w}Ni%ga z9WJ};^b?J;48!!$pc-(q@-^^Yd3@`d!v-w~`5i=2z*G%XKB~7-3Q^*;SXV5IFum)b zy80Njh6=s63}E$`^8S1FY!oP~s%C&y>=}&6kcHubtPTS}B|7H^3aQm3LO^rQF@Hmw z%+d3(hGMFWx7WX>3W%d@X&TUG2Up+CIH8mhfPtL#7%?vOmCR*?&sU7XnI)!gp!m?H z7!_A6)~?z>gYp>N7l=%en;kf_NGQNsbE`)@$l3IBucNM>EA)6yQ%jL#dnWn~BOIkW zm5*R4-j_7JJihW>Mbeb{+W}ljzp{4Aql)iJQ?I}Hud?H?u(+=5dkbbL-8Y7`j^U`D zgEKyEOufqc%S(Y(kPT#-Q~{W^3Yw0OcH!G=a|+-jdz!t0%>P^8C_l?B8+x#~z#;s{ z#YGK^E0O3Vy=J$8HkwA!j6&mA&|8zrK8Fy^E~s@mi^9{zNwLxTs%e&OqD;nNhOMYr zBj~{ktJB6->S4F8AiFgQf(8D&TX7A1Fi8!`@gHD)_XE&ch!H32 z@(HBgghiJl{P#N;S-8V>AiDK0VD0xilcsjYD{xKi*sw$kl{wGJ16%cGb`Z3pGe8rT zj(G3=YLH4txK4MUopF{KpgDh(Q*g`v-ctxV@TWaRh0E@Le>rU<-=b3bwZ|wvhJ+Sp z5Lz_ydUCz5f~kgg=Hbs$9w+PdquiB@hKn$m_KNrU&^-7nO;P_{Rpr#UY`yW%FU}(K zPYE4>!p$E$cU}e$ja+kHAT8gD*9Kcan4v-a_fPfuNe<)ZfR8yA1~t?7^?Fe@@p9YJ z@g5a|6XW8K32?KGts)jtGAf=qN&C~0+3X#+TJMYl9+oM^dgcP8KZ&Av4Y1FH^B|OL zL*W|ZPG^_kukE|M&<2LIEHoqKCY*U%Q#T1tkBcGSuBO*tA^N0^QONDlQTFlrz894< z5bC&^U2*_1n6QU09$OB-2SawW&;~-?>OQPGz-nv1mbKU&w5w){Y3PusWA*^TGUdFy zF0=^T7(-jz#G|Q8k(lTe(xT41KJWs z1r=w=%9TEe5}aa-rmiQ4?j&dIh+!e*MprNX+gdN0#R7F8wcX!_1aY#BcnvqfU^goe zCC@HFw>_MFTjEq;;9q+-2M=sR>LZ~}mLq=jFt;UWu;hVtd`cCMnN1%FyeRPi5~nKR zN+AcY@6nc(^q~-7^VAk!85uMu5&{OpW(VVpVD-Nc(RmpgWxvbLKnkBNpUM07mBO*cq zqvAS$_kEf;qB+Q|*N5vOJ}2W2)jni>cLH<6$-xl-MXe0b*ldb9BKP|)K(?rs^Q2WB zWMM|fpY+codUt#cHp+YNK!D2shQ=Yf=x=NzT;86i^r~~V@O!_tG1}>?-2R4@v^Z`E zyjr6dLD4Ie&lXJ;Tgnu|q>FsVub_MW2O59+z&pLDD5}niB<(#u z+MrnDQ0y05=lQ-Dl$4a*x|}{3=l}@q6_w;R8Iz^`uJinTVc6q>i;9>B=UBrGZ}tI8 zbeRYf=9cRp{X$bZUS>kR2Du(7y8zJO@r9D1p8{Nnh3*@t zV3aIVfeS3*8=U-!g@@Yk#aJXg`(!_3!#YwO%!oj|JvXgRgehq#ranh*QiG0z*heAg znwoxdV!DkfKK{P?5L_1F$aJI#1L^}LOC|CaJ4@!B4sD1`UmFJo@lVAW7Qo0;$)@Hkj&YY<$CUIIAh`tCE>-eY8QwwnDRnah)%UVz;q`%kL{%8n8 zTvM!vfZE<4n0sBb%+g;a1Oc;>E{^0841QyE?7fG_ChTob972Jnf@JKqxGP_Rl+WG( z_d^Q8YoKR809Q4MU388I5IX3HH2nq^O~_G9V+`%k8UVoXMje7B8zEbjh*u547f59` zx30#&rG~Aa-#3X48BQ*r28s7>1nCj(5uRnQGb236!*19Am-%}Ajvz;*Aedn8vJ1j} z!JWImHG9ygn{H?3oz9|wIXYJKFq3k`d$GST;El(k=){eU9IaIyglO-BmGbvm`w!91 z4D$vwY+hGlPX zo@pm+GIam6p7#;5I5wkZ(ZHcqSN*%?lR}M$%AAo#Msli-gp?GS;jBg>+4S)lry46G z!Y@=6_FwW^S4vePQ}}#nV*xVrpzMniLBZ@Dwc_?1F8dr~!`AO$Z*rm{7}4}ItaN`b z!&ZZ?(I%}-$HzR4@i!!;emZ=7olMU!DHj7%HK2&WYo>OTBSa}?*9jfMT%#5UWTL`$ z$Je64U-;-b??g5UZfx#aDRb1^wcq$`pSss{*;nJ)jgn!@_4~hZGY@ZOoVx`0fFj~b zm;H6_k9T!;UO$&wm;4hhg(6UABD`IrX2Acy{KFj*hGzUPX32NG?jbeHMC2dF4Gx`%T>$P%FFYu@S#c2bsI%>utd~!J?;EN#RjIWNs3e-v~)piDc%K@EjE2T!c25 z?$?dgJI60c7z09}E}iN3+<_^X$-lK#D+rWT!8W`%7(Gu`F`wGIs=p|7hhR?-fVUIUTeJKi08^NbAh{_z!&5=1-CZw=;S6sUPeYM=HV0k zs|Tkb4a64ZQo&l$;s3=1+dp4l#KVXXL*4}js1H^o+eC@dFgC{DP=XHEWNvSB^N>fP zk_a5>Bnp-7>x5XU*QlgLm@>;xglU5G+Hb@?YDL`bFxLLyV~EYlF1`dad&=vg@sD7I zT%1g;qwyQiN*}ZyrXX?v9l{qWwhrxySDO|qm7=*3!(&YATdDlC5XX+KiAYrqpzjdf zPYTSfwhHo>{|F{ConQ1%2k{S3b~`}Xzs=ADL9n^pwfgo!FkhCryciIKK%ye=wM==^ zHetTA&J`U!Dnn)Q+z{ZhywcXmErQa&cm*E?p_ZMX<7o^VjR|x?J&;Tov{sFUt~17S zo(D$FYb%n6+d=2%Mn-*>2M<+BaTj=l#)_9+`ppcv&YR2T1~sj8Fawk7=t~Gf*2pRV z>pV~IEqyKukzli3kQeiG*TQu2OnlgYT0y2>0NSps5DXn#yQY;$U=a;u%wV6u5~uii z1h@4w^gL@2FXI9ajOQ}uP3vfkFLf!I9+a+p7)Nhf4+XM-cw)t8?R1{gh#+cTE?U*4*Iha#` zFpK{pd5$dN4rflVHfwT$Iue!?kDkqNg`4-)TwnroIL6Y@z}#kgNfd`TtJS>4*R4eo zuXlo|{1)I{ThElm>xT_wPgVhaGO3*K*^U59<#yAn_+?bo7glvQWJ*s}YH(jk4uT4v zf2LP%`MD4}iYs%;HjrFs+~khJC`P7#O)`U2&NqNe84zRZ!{COju+BM`wQN7O*T zu!UqzgS|m3;RVB4=uwEg_BN+bs>h#p4myl~dT~Q6#49}t{8XJ18#tLKPdZ#rAU05S zV3|0@#p94-iI|)*5l*uXsr^mWrpCsjlRvs8J7cbRah0I+E7$35Lmf3Bwd=DCQvnmK z>KjeZ>EVcsxPM~k=%|kDBw3lj0Rj4x3DD7O4;is;Yh#YF2AYLqB-ri@RTeRi%Wrk^ zjHnidLL2u)88Ppns`0mF!o(9ia53gf7;$dh?4dpYn;~BLU-BHP3$OVreuft**pBx+ zqZ54eC}48S_QT_&+@E0th@4@`eFq9?GGW#S++uht(ITO+*(GdLH(C#o3tDG8O)xk) zrl@?k0ZP$FZ$eB{Ln`RO5$HmD#m}BiV8WnSOHqK>cvseMTIoTn;0ZIN2&axDV?g@? zLYV3ad{pDw%4?yVO%HZmpBj;H*5A-Ggqdzhk&R)y)gfu=+uR4+ErL&OhhOnK#Ze^M5%yu%&+!K1IRbsl!4h7WXRcJM z6v`m%vhW^8I)hq5L+zw#UV;!GG!N0<@V~okF+<-4f@|(q|ElMI^xElUxmW2ojz|~$ z`{1O@DdB*eK#-v>({dQ-Ahb8z|EOzWhLBPVx0a8QnNlXDDatSz0{zu%2PlEu%Tc=mz9f#QXB9KbU*Ag<7w6yeOSH8C$l(mFUDHv1~8x`3WGrgUp7{;jW}r1|guK4ZS4 zpa3qU)c~m-zo%q$V?9a8)QjcG=I+?&8}}MbO-z`(^Niyl^h4p*t5>td-n(00t9^W& z&y<#&@QY^SHM=BcI|KrTRj{aJ@iohSe{bHbRdzk8Ve)0_XT_f}hN#n1vKa<5lTwHe zDmq6GOr(au*rFnCJwbetZpZ6KxqS_Z>enerK$Ll#3=QJV>y|9Hlksp$GjHUb-)nlV zUUU&o>$#a$<+YW~V9ukP`)r6HbnNWhaHV)-@hXgTv0cKlUyS{^-C^Hh(y{ z9RHv*E45)Nwy85%eWAdd6s)5E%}K|X)5Gwz%$gS$AJ&_ zd(k>|qctq*i{-YV7QJ7&huvuh=O*dZ;x+5P0eUQC#$+=Zqgh`OZ86>HN7{-}-#$Q8 zKtB6_A}S~tIs?+GT}9jDQ@(Jbm+5|>=e(tdM}rlLgZmi{5W_vNaYsX_Z!)t%4-^0J zAkEZs$bMUq=_HQ!zg{tywEYYC7(16wjeg@XsDjen)YQ8H<2vd|j=mRC9=`Hn5zmG>E-duF+YFgiOB|cku6#H%x^t)TX5{0?qZ$*R?~X!fvK5@?mmq_P zn~yK-(?=~Y>z-UXB)ow)gsBQ^r+prRoeCY#L^?xkLuvD?oI43NvHPHr;-a}|rF(xJ zscx&cy7RS!d<}cEpKQEAt}aEY2XlabcMTZAQW%aBC}bXup-b?RE1-uJs}XCB30KAN z($Ns2))r(epqL4!;_*C2Rbr))=n+m5X2_vx6@2GvVf10% zSwn@LpZiaR9kbns3`d*T!2Ex7eRn+7{r|T;%O2UK?A5fDQCZ16)-j4ysNSmg3SC8rpx@yW82a`7wseSZ?1}nu|c2mN9T)5ZK1_0 zVIWbY9NP^_tXZlC*i9t+MQ1S-^*1{9*U0Ooj-K2;0Cb&v<?OZXG?0?VjxDPV7u?&yvaQ(gGNcU#%YF;Etn-&pyhDExr&v>-QE=H7W9^ z?Q2<9ocs!cv1s(c^ADDpPVNP?&%Hf>+|YRad;6{5C>#FAR#VgYeqWKaYl9j<9NPzo zinft_B_!nw6aEs2A4P^aRNijWZpDjN0o`VNb|pz4F4fIM&Fzap=+8pGdEmXbjjVt{ zI}bG)#Eoa!Uv_`wFEsz|25^`E{E0Vk9|yks z@AFfR8v)&GF6L#MsrR8DoOK%z6T_~7iOXQ*an3O(-Bj^gv6A&yV2wo!hXE^yHmU4A z3BeOZ&#DV{Yz2O2s35k`@`)uFcIh~3^8SzAYx3s$5Bn{{XhonUJ%97}|9^{5J39f$ z`PLkMU~G2W|K~?Jj6dLu9A}*RBHSQJ3}Ub_Uv?p`bw>ZltvXYnaSw{y{f4{xm5*-} zOmUCIX9pleF2545Wg3j0e4TXWHS-5&Wlm0lXEGl?8QOF9%us%nAy)~B=mDIqX1<*m zYVwR-hIOVUr&ngpb=;Z@0+s<;^uJVY0A{y``U{Q2DToPUL7fSYALsW7D~@gZ05WoG zXuO#2wOVi%JJ4_z37}=a`CWZD+xY9{MMD3BbavU^hmD%*j%3>u*{adW&@lz4YcO>G zzWpU+h!v$_co+tEi zIs*6bw*4pI?Y0$|#ntJXuC9Y8kH^Bu+Ym@jzSe@f?Xgm?whwGR|JdYOd`bz!_gpF! z--Lh)2C-ow4`Ol>U@q;cJYTG7mx%+eaBtw=dSGv< zbW_p(ypd{9|1IeNgdy$7s-=0N$gZpp~=OYHDgyF8+8 zdah$ZFH7dcTPMbnt~gj^9sL>atj{TJrMktCFB)cxgsUV7tRR_JJ8%3NKYa|-RW`p! zYv@(n4YD~U)1|+ z1UZA6-$bn6E~qA(n{A~Ks5{}EucihbIEZ`VyV`~hy(V)DDdhqIM2Fnm^hG|{>rPX7 zP`_pN4{}j$kGTmui)+{Va?bkuxa%OH1xa2N8HtIPz|`Zg_OQr4giMjhn*R!LP$NUb z>_0)S{A%?$p92`kd5Y>x`w;1V=9j?RpiY=xvTh$xq+fXe?IP)>(y8viCu#wtTR;KH z;>BaW>3?(vo5cU@et8$9%ntLv!vS~GvQ$a&znXHuCLZg^^xpd!U0CtJosg|cDtg5v zShgQ+oH{*l(O%GeQS|uLhWkSbPY%bPAEYp4vVLKW3PLYwa7Yu@>d6_qd-8Ngc;0i1 zGKIm6Y*fhd81$$bEvk25t59I{u#g%naZ-`$a~le~@W8E=*5h0sJtC*bp6BQUAf>@j zX2ZYvoxafv_+2(N2ESqUk8;XhCWqx2ycw`Ov!^m}N5TeGOm{CS#B6d2A&srFj91PrYnKhg|5%NEL0g? z?(^qH#iqD9z=A5ka=L8og<2-rq>t&V>w2GSeerH@K5^1Y`5LJjy$8dtr|?@feb<-P zOehylOZ;=>gxe;#TSUt&Zz=Im7TNbZp_0BBySln|)TmGvMb7((6^bQ7d<-QerR$@m z!^JQ7&xm$Bqxh5Ae*uxt{XZHy*MQ%s4A_9$rrLX@meQ6yVSm5~bM^L|u(0sUQ}4Bk zEGvt)-;)ezap$UE4!=)EDOeapPIS_+1sCjN4r`y2a5je=%JiWQIlZYddjbhaa{v5ikFQ{ zIyb|Ng*c$hEa?Z!ZxotDN|?QT1mT6>25QJNWzZG3-W7)8#qxDVeoWT-yI%R;mtri$ zf3_see9D?}q-B`|zjXp(PmEUlgASUzRFNgzYoI;3yL6{62Ml`paQeE*l1E4tj-fsQ zhBESc8_j&XkY#u6&Uk&WxPLD1I!GdSP%T~u=|B(}XgIF`c3Ns+&l(>_bF=61|D%ZX zLp96l(Y2oUOqIQjWHi!^_OMZX^fAmjwWs>fee!w+Apn>swS5gv>HkqeE*YJv;6@c#3Jw@OBIxU|8a zZ&sZama~%216dJD!ACRB-W1`(%)KtR)spb4jKz>cQXO zS^JPDb1dPZVZX0LdX2~P>w2k$JRaf0`@B@R>yA}1OEGF8a+`r3AK>~FFe+hYrl+w^ zuab~$!u@Mr0o)3!7vEw;b6tk^dCzh$8&h%%(oTKld3zn~Au-MS^Dj)oe+|L^gBACl zp~TI0dW9M6wsQB>oN6^$cX9c7w1oc5cTymn;Fd~9P+w)SSWm<3dc>OoJXAx!MT;EQ z#cummM|YY8b3N9WS&-RL?MI-OYE0 zn2m{VZSsdTao^?5%}sI7MX)Kl3A5_4`9#C4AZcX5bHt0d1z|EfdF}oE;dhxNbn(X|chm-dP+n90?k&_AEv;d2dNLK$40I0=GnoNgKuyvST75yP8WP)AKYLpfe7lk!9t7HkOW#j;AyD@K2!> z<#a24MWlC$yb?KTq^^C4%r`GT-`LSnYy{K=6*s#0%?54!en4`Wh{Uw8Q?p4Fs>sA} zO-ILX%m5Bk0xLZ!%(W7#*{4w;G}InC{1i&eeRJ+2m7HYcGlJ@CLzzh;!xi7N$aG(ZJsoaeth8oTHyv*uO&%Z@hP!p&06%I9bm9+-O8 zti8_glufO^QY0_8{vL(HyuIOY?OONIIAwLY5sydfIy30$i~R_97W#`7G$(tOswkZ( zc7ZnpeTozl`povlHf+^R%U8aU6Y2EpuB?NYp~P;YpPIm)5sSNU7rgNV| zUy6Vj!i3%*#1PreoNXC&MDE6M({yWycbqnO8Zqzh(FtVCsQI|qUB)HwY7p6cB&h## zce5+dv|jTe;|Zz2VE^?7R|#b<@=>&r&}*lDn5{`AIBYJ65Ww!}NRqnJn}HYjbClQq_&4a0 z7Xl$nStrjO;eKj<$Z^g~BRLB>uJMXOoPQ>bV6Ek|1;$0UZfJ{}d8r#ps zg4KTp5-BTs5Gu@$8u9oFjaJxSmxaW@qLw)#q zsg(ZO+qs&t-BO+Oi4xKH7T9f1`9+(FGM%8b8Xp)0ZG>=9T$tjWtJq?&&k|s{;PHr_ zs8~NfFmRjsHcw2I1Ta(FfSFR>Q%g2*-UOOB=A=_u?~x#D<0kR7d9bVo-aIpFpS}j4 z;z>e3%XqRtis0*EN(|q1#F9IrGCE9IA`5VHFx5A0DL36G``Z?2evl=_i{I1E_R`hr z0~vmU*QTxWV5y$I%37kES%Jl?=ZbzQeTlR+V7wSP`!Ur_o5kC05}baFS(_21%shzI z$|`CnQ-Q94s+3wlY>i>TSwv9ymJDlp7}&3TNDw;h(3V)RV5{tbkOXsp<^f9ge`}|J zl<|?HQgkiMV}VhY&iC*+UTTIzTHc%9;C=aNL#wEXYK^D++nM62&#uMKb{;d>=Du=v zFDxOHOgc%mgWXaqw@D7XRqc6y%P8T6IO{d}Oxpc4@Wq^_0{{FJI5P+&^+}tQ!3c@% zQ(eka_b8V^;wAt7t_ht)BOHE4fvR{tTN*-h3Ms5f5NDXy1tc~yj_MZKLN|9zNJOFq_pCvkg<6ztm#)=c@sqUzrhEzZ!v>I~ z?CQMfmQ<=YvrCEF-U+;d@L}fP5KAo_`@Ste9PtuAa zcMcd>y$rYl2ZTRl@}5K@UO7Cfi`}=BDZBD-fe`o)$z=R{{{;$>Sj4lsQjO#uC>bFL zbog7hW(p`uibPON>ASXjTaV*D4^dFwGs_YrB*8p#mo$W^Q7={Xdzc0*p*5pkEIn>2 zLWMsDhSRw2(+950kRna25SK9=?HsF{o{!q!;nd-drajbPLxzb2kz*wCSeX$1xis=d z&#evs$=xIp4T$h3^iWXg0ZgPC7`pE!=*pf3$jbAtUKqb*SY8R6bjaP=&e}Gr1uN1i zFIZ6=dlB+V()>jbKeV}D(QiI$!K*dE2$>E45%&G7fvA3m>sy*P`B`l_AaFDBHwcFy zNl;bg!C{76(OLF*ch}vmSd+-HfNk6+!+F=HmlAo2b;6IO1!{6}kKveV^I(DZu%r7w zjwx(7Pwh@H1{(0#_Yyc)tgyb7>qYKtc>&)SG|Z& zx7O?c)5=H=UX+rXdkT{RPk&6c>Tk95ZuWSdZa$@#Q;?UHxKF%^PrUBm3@kn&y1&)a zXP!ny(K!y3Sonlwd*;Y<=IodVQ90r%SeF%d|HX4kQhqJ#hbY6~lOHS%;a0wTT=v%a zTg&Qog`#GI%k!kf#PGF_4`5i#oZ0SB?yEiA1{JRlA|VXlE)~cNd`i}-(m{%Q41!O`;QG_4#VCqI7ZD??L@luW6cXU1XEdH z?|fxzp#+HOb=Cjn*(}+M%xk6QPu-Ui@mK3zO7_3F!9E7A?ORii}w_-iguR;*3pfdUOpssbx@UUuI~eI zO&}+oj9Icn@nfnI%(h`urcW%XUiw;ET0cE*$_u=A?_S-%h14zMTL4S;E(h-UdR_x_ z5RO`~A3t$7vD_cVxDo-|f4#TxQUCA6>L!dtjHX?D+`fIf^iCyj@Frr3!ShNw$gS}V2Wuf<`4s|sXl%DxKldSb#P z;q2DdLfJfU`kuExmZ?D{cMXH1pkAEvYJ_ttQBpZzhp?c+k)?W!Eq<&~6Vw`<&|1+d z?7selBf2`1=QjZiV_VfwinRu0_pBEKh?!7ftgusD9_X|Mqtz=)~jG`Sgs z*MOWxt0z{RZOD528N9yyX@3}iPz=m_{?GvhL<^lWU0(IlW$f)Q@Utokd6drqxXb2{ za`&OL00Is$O8@WIq9Sk?#QH_u@A?aRji~=X3<0;?yw_^SP`5jG7qfg-hEICf=phO?ZsE$=D?)H!3Xda`(Ik%XpHoYum5$_U_1Q} zUsIEpXlE*6kL3_@IED_y%FYGvz_Gi@G&4KXlhCYtt9xo_Ve(+DOIFxH?jG<9nFHQ! zOf7kz*LepI*F8!_d~Fa2#?@oV5Lve1>!a|1jlQMTuksC#qLF%i&K2XkSl%+{JGPzi zm5zU)t!f^cP3f7hM`O~dys-#=9(`%ya=Zd$OHHm4;jocEiAC0(l$epzVNrDSj#Nsj*>h&& z!d~*acGUeTr<#y!4%1A%vaYR?KgF?MKC;~NJNv#V!e}oUi{3_PVtx0({oQNfVmJdd zSX83VEP_2;iQGz0p7s$hz^Z3}_hZ1vg)~qRI@EP(w5nvBbf5zhLZk0{;9&U)f)_L} z^h%aUh?cWQ*&+6E(+g)hWPm(gwpqzc3hjQx@cO>*f|zCQJKR&8ld%)NIz#i<>BvO-JcrrUHY^VmT<2{sx-cuv+g zH8S;WOG-60Zc)`x76cKq9`Shc$U-|CLb?>{lr7#J^$yp00Q21*$vwjvI2^cpPTO%- zCkZ;ED@HA6NDKFzZON+$@Od?Dym zh*@O>n%L;aRD2eI0OIksK>_f}=jP@0;_RsnA6f24QgzyZtU zv$aW613=WfdQdfm#LBnpQ)uni5Hi9zfjxPVc^Jl37cS4sS2kmBE#nZ_#uhLJ?X+p% z-;3H778Z$5pSF!(;s>KmgI)0RO@$P>rMe@1L1b4E8UEHz@demfcc19Cu7L(o?pu?^ z1k)ZG9J^pC1Swl%5y?E=sdD?KFo6D@sRs+dVIu@z@h6RV|DZ}+;oQfx6GxZUjvuLi zl8O;@RZLZI4N6jbCUw&|>-PqBQgS8uA9;vcJcyCzz7)swt7 zHl1mHr>QIJU5KcRTpWj#4Vx16^_-*gy*04sJClWyF#8ngqCZsd_0w?wO9=;$t6d7! z9xG%?R;!un0Aa69(O}!x55c1B@9SvTcc*)M!?2zbqi0)CsyX$w6{lcCinpw|f;8>0 zFgi;EWTlv!Riu#5T0^9J0cqT%m=C+$NP$v$oqFgPOAC$*xHD1Kqt$abUf}3{;sbUb zEWKjUtNw1>psIv(zhBc7Y!P4@UyYD+tN6js-`2$&yERa*0o?oOzQ2}U%qmY!@62@v z!=fN3!lRHtc!B{n>Dmm(L#j^^hLo@Y)G25XMWHrzbDNwZV;utY5@``uVviW>sS ztbfRY`SbK{zZ<)a%Z8Z0ch= zBOBF+*}Y}TR^Lv_+9Z3XDdtzi??vhG8icKDxmHrbV{5#9fH)cWjG@5jPkORUdz}TT z)XW%uN6EB(wXM3~cC1gSV(Isp?E=M_b~25m<)bT!#ZoqJt4Fy)2DSNyTdJ&WHf!mB zCz{VJ+>L%c`9UX>>jZVZ(3secS=-^qel78D+I(%KtE|-XICTp))K4UxJY>+(ek@*0 zr6t)Vw!@oAoV4?m1rg~O!TZorfDB=)Kz7_z*nKqB_ z#6BN`3tD(%+EYNC>zG@70K5XQh#TaPLPkHSQ%*k{XThPx9$Wlg+ClJ&c&YW|+joAp1DQn^fMDatYugTlRj;GCt;R4Lz497 zj+znsZ$s6@TN^jTIYIF{LV`**o zCOPB1&){59J8g%mK`9r{qL@VPkrbFp?Vl!E^j*zCSoe|K}v zpF4B!)vH&9fZ?`P9f@ZG&2$dnofJmwo>{8(bg;mac`jvASVKO_%&q|x82r*Pxo-n5 z=5gWi8b-$n>ENH&Q$_zB6^l;2_l2u6#8h?m4izkC@-Jr^F(|0X1@YYjtnN1wCD67x zzrbZnT`40T{=EL9+(=337bKc2>DkE&(-&r0e`^7Blcf>Qo@b$kWv2ks`swZ7I}72K z`>ym zs%9x6`$PloFiB53vQQ@*&37y>T#>LSmBtSAuf4n+Y)lu&w+VIt z5<5a$L_16i-4^XO)Ptm5KQnhPxGC)9jh;FnTt?up*#r2#e(<=N<4C^y2^?0+$uY==KzIOaW=$D2IcN>PH&s&<^xc-AR zWtX}jverQt8U2458NKD;w91yCJm8)#WmG1#WAj#Svi3eb234GT9+>~y3Tp3bo*dz= zQ~q)4+6t3r&aF=k7ZBs522_@Q=Gnd%S2Zll-GuyoC(jc;Ufm;Mi>D=Zy(Fn%c4_`h z4+JgVjc~g>-F-^`obl3R+u=Hbbd(DH-+Kl%lO(C^wgfAR05D6f0QxEb~CBt4!*VbFil&#wIu)H@e2R`y5 zjCVPYNv!Br#qTV+y}cvv9a;Ri-qxyXvM;6_d|TcXHaQ*8NzyR8Tu|h;rT<6ny(de$ zC&ddlX{GfU_xm5<(#ie2R1Sa9(nCIH3NrTi;wQnS5;w|33A!XQoBWZFSr`bY(5`GQ zjaQ=O7jF)F{&-eiHU)A&UA|L@^`8zE{xa~jj{1a(0?d5cZwRZ1#wO2prP^MNwl6Qa zU-sqDxRF>jdk2caQ~R4$lKNxgc~kS`<>ixqK8P09@U^dkY0YbGOY0NvluWZd+=$3E zj$TpZg)-HHhe@4*_P`8doP%Ue_pJ~50Y=^qL7?TP6lE)-%mcDR%Q4hs1tok8M$#2+ zBQ?=ern;7OHoSO-`vWw;>CA%%1}mR;0!H<=))#nw^-9m|wCEyEbp{2K&;KekZaX59 zd+~*FJsotQsV@8rSmKtCPyKeb-5dffZ4Z{*xq9{L+`+3|L2OLabsZ2rR(&nfXIw5T z-9YRbWmEQQ^#IQC=X1S9lPbAsuNU@Lkmbg|#>sjd+J#Fe1_CDj1vh1@dWbVg6NFww z)SIG;%uuD~sEzmK_sTbF@0B0wVKLA(;&^t~^vXuW1Xv6%y{R%>Ak0*KeTXi`e2dI^ zOt|~QmaEa~Wl7KJqV+epo*4B283raZLM(BIKIaJ)o|nO7QhjE}KE6mif6xAkp-uBA z9V>Se#jdDQv&)1c!J8=8;p4a1!=^Dc3|xwcZql3(wCeVg_}V^nf6rqvFJn<8XAXse zwWEp!w8O1pwTEWgZiGvRRWDA@a;{{%H5+T_<3Fo-M46QO2h@GJulGhDVt7?54* zIVIm*ml%C&kflF%wy)soQ7@vUnn)}lZue)|?Ln?#w?RXRfn5fuL2>PF2lGowDf`&7 zig)7f){-?`t1W7bH}ke$8?EdZk+3!W;*i31Qj@QxICo2W>a^=i8|zb1AC8jSm->*! zeUSB@*@Hk%0LX0q3y}HmAbfawPU({A3Qqu`knrmd#dU%~A3r=2*+n&ai83XUUB)f| z*+p%h!^r`t%`bV0iqK7(04}2si5xI~0Fw9O`h*F1`^|3YgN{n`eb734&`rsZ^N+a> zv&7SYj};jPbz>wSILk7!n(>>Hl2rI)cnhB4A*u$(4%mi8jQ(woO9PN3aM4F#c~$&3 z=$NG9BX`PqzGQF(TiOi8%chi;5+(g1YCea92LxNO zPoUq=%NSx|s;k>keaw3Wm(CBq!|(UHFpu=siJo$|zp}l6on-i%sBE!6TJ5%6dm=}I zB|h+2WQxYLUJSU(sotOQ+ks{BRI6FQ~>!h;=mCauatmqDK8G#c9M9s6j z@4jbU@@r=7)(7v)l~1|?y$`t2b_*SUyn}x2P0J2Oqz^BidD{PS^Amb(x1xd$BE&in zev>?=svh8ME`gxLM7r?-Wp{`(BVS`RP?IJL_^~#LdJ#R=?wMny(YDu)H@jckcSgAJ zs#8r`f{DMTQl~#luHLY4S?3}4(ZKcJUmX3q&^Ox>#hi@NoS&H(sD7m|4LyDWUvL)h zXM!bGD^{FbUV|&d7{~ND49-C>(8VW)uqZ)E3&d=%1$^<0sqm|A?oxAVfa}Ggr9hS$ z{4s=@@%`XCG`3=rS8zPpjX1f#JvLyRJ;*zaCE7vIco`YIqb2ef>*r2<=Up>Pvhu)h7r=Z~D$uM1t;1aVgO>g`dQ=n)B?g6H(o4WIkb$f=7Z(0SeV0JDb)1Ly zQzDth(7bRupUd?8y458Uo;{OmMItAu3k1e>lRw|Gi*pIEov4VSo3%45wF|47uDvH4 zBf;fUZ%~i392|VE$Y-p<7^PxOm-~}ZlT^!n_=n38r9EhyRXZEq&L;mn4%V%M=Y)ik zF1{eY^=_Dqh1#6$CmpeSfokjO_A)q!3DyQ_dLLL<`YOq?a`--Ho_HA*V%Xs=2WIa+ z6QP`aVGz7=Kf`;LYh4F`+5-~f6o^e}0Hd>+EvCD2n#Xei+U2nV4QP+#!wJYj6cH$J z*4xE{1@Np%Wb|#>x*Y5DR_c8Qp?L260Tx)&T#;Oms*WDjN-D5j4hFB8=&v!Hr)b3g zu_$_sWK`GMxi3f^nqJO^aw48(>sv3+2p(aRz>{qMNv*cufptCAoU!zNc4xZv;n{6r zPE}UnOIh|Uv705~F~3bfLs9!`R|VWrDpeR8W^4I@8kr}Kb(T(7p~trW!pb`JwE~RQ zI{-+@Aw`pVoChRZg2~0tRf%?I1x`_k-9vW;jd=-C^ih1JR+F7Vs*mffCU3Fi35jB( z6}A=m7L0JF*w0aY*tYdJKSo-4@i7hfqvi(7G65-t4eKUDlXp{}3F%+HAnsqAs<;Pu z-{vksG?cY3pyQ)Cp98`EX#E6RcuU>xcNeF|cA2_ME_J)FeT7Pb$-)p?=xqQfxhDRS z3&4zqOe-Lb>OFvwl4U&|n*(>=xeXX!oX%pq4^!b!f;CnG_`Li>;$8<2Y`oiBSss2hs+^8B>d*5l#RU>a;EQqbS~zb z7SuIFI8}0p0#X$UY!rkMikDK+cy=NiJ7}l|P%__FfvvW<0Uys+d(d}ecGP3n1 zzFTZleTO@L8D)jPp@?eNI{D?@p*RFYAO+3F_e1jUq+E$lL2#S!E`DtG9K3X9-(hC( zKFCeZ1M6%?I}i$@oX)$tu;zzBd>gTrWk8j*5%Fk{xXb8Dv^T4`r> zU^60C+7nSn6nFoT-C1w=d8=f~$*pd>$$-sK)JNPt1N)ynHO!f$M~;1ffwJg zATyZlrXt>1=B5&5XA=x!Bp|KUBH7_Sa4>Du-#0nIQZD=lc#l28}j_*cCiupOK_BhbA4zBp-OzNXYU8m4!tL zdq%63-388P;@2Gw#mKD=xQS&IKgpKXu54Yh654W;+9Jn0RhDX0ei=M6>3k}&RRZKF zVC6jHO9L?o5FCah!K5D_3zm-)6{{(`hjyQ`I_S($cgF>2t9frow8#ddbQ9Q8idBCg z8@MiR+KT;bHW0CyP^IRcUXX+BgE3R$Sn2AXzkYwU*+E`r8P^> zY?x)oZ8IW!n8biWo_sMPAb|T+j|SarsCv+4TN17e_qvsAIx#%gCyYIZ%UIRAX?3ASb$X^*U&5vAQJ-hH!}TA^JG_T8h<8(H%rxQkMdx> zr6|)I=qb}hJD%(3cjlb(Q;7mTeTIsUQM)OKjMX}TdQ@O`3$wd50Ni|Bu^YoMvV0v~ z1Ge$_JCASEVwM#{uFIOf-SP~F#kSv%xX~+}WACXbd){2mGRv@=?20#V^Q6K**E7C+ zV^*-`MlLL=jZOU_wrV{=AF}L!Gpfmv;)e>|rov(tP2gi1xrYZ1fr@WW@GkYu@70z2 zWM*D{-T147XAaJMrTT;C_nS-}@$fo)pc!3$FB5{lf z=MskyP5mx;A&V4`d6gmf=OuqA<2?%-NyS~ElW_2h&t|DIXQ&n@|un3!>%%mwN? zNg>Oc^P&uyk~|GIVMcVIGRL2}zidzF%k zGGri0zrE~U)P(x2!o;)gHys21fpYG1l3=G8ckQUx#@t|?03UcRIkd;LXx6)7C61=U zh+W3(k`-yO59Gw_Y`?tw$qw!>WlM`f@=0z5zhnI_=9#mSY0T9lrY*j6UhUmt#^{ai;1N>>? zKi6Llmgs(z&Td(GD=&@x_wty)Mr;9B0@>gzcP)V365U%tH?QtQu0&a?x?8e!jBzqk z(KCS~`39QS&!z8xDg3K2RSwGR95&Bo{<0FD8lI3;s8ZBR{S7A9zuNUQHnxvN*O?vj z?bZHc119;Zc+5zm@l03@&&@7=ASIwu3m^;NnCjji@@+>crE&m#4}%rcALpIpP7(h` zd_Pq}HmOHUcv7wFJ@nqtA5suI^t6>W-ChJ51*nD*We-?#ZLqb*O#Vp|H^i{XOtI-9 zT^!^t(#oHJ^exKEPnOmEG}+pnz3+WvL)$3zinibdXX9*yO)0Y;nNTJ4kU%p&e;}4Y zK-MZa$L$m+T;6W{$v?}}!lBt3v;{&CKRX0%AYATl&|rHJt6_5t@;B&DXt`Ly+^34s zzW2G_JY>k4@|=e_!VLi1jU2_4vY)AvMzb+t7toiJHUzW*JJa13MMVFuc_gq)`H;N} zT%hkPW^^Qot?0#3xU>XcNzfp{5f?dtGW2kmodQ|H9Hob$6?`grz(-B9_CLc2M1iqe zPhE9zL2h24N8LOODDN>pZ*#!Az^xuC&LSZ+(rJo30hO8AiVRACTv`RNuZR;WAqP$Q z-E|+fp3U&7m8*+{q*O#|RlFPlPD4u~jg`^it{iGP+&wQal@Dq+x90QP>D$oo@ z2#-`x8c~=adAcJKR}ZosFF_#h90)H7f^}XHva!GV@$(svD|@7W5!9mj&U-Bn>+#6l zx(@_3=)}Sf@IOm)<&d(+lpgK$rXkFt`Xo^`TSu3(M#lQ zfG10%i;hx!{*?nWDc3v~-4ppo(S1w-(@`7Ozp|!?K(%a$z{gSTN*sS8V!9AL#Zl6- z8=aRO=C{|n9`CmYpYdTVi5>%lguq${_R}q7L*yvILRBXxYi<+(fZM6V4{vebrbN7E z$JCL#@GrEyD$W+X1dyz3pj_==*leO#D#^_F@UsoUpX;x{3Hgsi^9tZwqz@(TlRzmw zpb-rWDOziOpn(1*4S@7#i(263(?EH6XuUro$vo5S{T8*KT5P6>_;DcH4zt0obfvGB zZ@nfEmGMmbW7`_;XU*DY3(NKA-1NTyRFDy{ zB1mv1lQg>hjBl3?{+*EH^Q-u~0uZgcs-IXckl|xb5h^`W3SUGRt07`(M*Tx(@y$ce zAiGas{6&wPuy3AfsmKtBGkTi)c)TZXG{Hpp{MT=`{5=vdpdtm7Ma1)08Svk2?E{(F z2>lcMe^rf_O}1-!>GkhkB|dMW8qbf$<#Xm@F( zx_9k1@P_Nu@(#t`QSlI{vtn%X%+A&M%gjjYJw0fo&-_LHsaZ07b%C1TIp)9q&Q-$c zqWnrMJjL&zelurAs@Dn1risIq(n^?*Pbph)5ry1$HDb7*nwAkAUqUrA`>Q5KZb+nR5~-8Q#1iE;*@-syZClL&jG zy{=L3dR@cx1l(ewN*Nh1* zSP(?{P>_a9*ibd1ZqK`ObXe)m@*?Ce_;z+Ip8fhWxJK!F+Gd91cBgxW*+|@-VHefd z!GcgooM^j4&FDlu#M?5_z9i@JNj<<@I28S3eD7DUz8kP}#VlUt+T@;(Wck4{}xvKENt;{)RhBvJX>DDf?3PPO5~WZx=7j**1}jY ze3#!G|N2}n>-HBf9YP*2UX-Yl>Tr@L3oF5;lY$Owz;%>gx~|JSVJh-m=K*>9HDYuF zPQE+jbQJ`c+%v3AIdHcW^(+%E4@yV5;pAg9=R?t0;xnuStzC+3uCAF7v8RwF3A-?U zC#5V1eMu{*0eAmyNk=ZWoo*ILg#>oam`bj@!CDi^XNaNV&#=WzEDNln#Fw#eR73NV zE)<;?LWG8#(&pw@`0Iv_WQC$Vh*9)ku8~M!@+^*rG~gQ2&DA0+AIs?PUXV?nr9U;3 z_>1=Zee}U=Z5=|2o_Ds;(;O_!H+>9y3#JCX+WKYOH0*3A38p&8O=EN3Wz!@2&E8o) z{K=rx6T;&UdN0#T{T9_+^H{n=D>2a_N=k#@5^s@`2P%icQN?tD4(7Qp>qf!7!7{5aP-Jg-}toemYn#BvaU;Q-V9NQH2 z=bThJRU_6I>er|Tvt2+NT&f}Yn|A!{gY6SbjRb*LLqb7c4V2?171+9R;2RaNzk6&9 zAI6&xB&I~2S68S)(V&wg{(|Dg~6$Z}xF%QuvI0M=#bBoY4b zZCd5Mzj{J9D_CdqKIf;qq`Pl*cAMhPK_oP`e*hedA$Rtl^XNTUR z%Ovvp)nc4kfq@Ox+JYqN^3bJ;Wa`_GTxIC+%0ccdv=m7}M~OZu4N_y(G%{^%@WH(i zRVqkhFkfV;kDiQ16*Z;Tc(s9d$#>Jv&!>aIvx2t7h*QR}@W>PKPg{oXm{SHGau&rO z9ilr@u1G55s^qztYuqadd4NtMC6ekST{&lp2IKpkO^pdNjcUPvJ-@^TDFH=Q6z#-- zj2Iluv40=TyP!pE&((f34QVPe%BLd5>NY>RP|UMfXdQk;u^NirQAyJ-{qefrq&7>* zT0!znP8$1JGnsGZ9W33kXu}B(K72(+sGSe7qW@rs0nlZ2xGth2+H-=y$mRr5O=X7dX*d}$Y`gh%8eU_by( zXW!+C@-)Qmw44rqn zNhBL)c#ez?f6Jh=?C2!CZl-6MUuD8m(@exh7qWcpiM_Q8AqJ=hsazenO{iS{`lWCq z_;JXdouP+Cc5;u>izh-s8{1cA2&j};bViom`&v=r>Un-*B#;skAr{K?vf}))kyh{* zYJ)^#6&{F}+_PB0-d~-HJJ$x5uA)E^{B4!Y+Nf5~jHzAyAurTwUv&PQ4-RCuZOKW% z$C1bnS>Cy+et8g%fKc1KeYnoY^DR<=43so@@gi#cg|_*ySoH60lHl6kPUmMav8@%1 z=gKZps23Fln7?Pf_4XHOfV`LKV77nTkGNR$TaRE4Ouxzc6sm1Ap^)YKy4rB>_YxzKh5&NH6GMS}DDx zgwe~#w!c4ubv#Fd*Ky7!GCQcgvrAT0@>F@}=}=Xj(e2tU>3nO~&!L0`{;Z5!!e}r(TQ1m^lQp+pF4imO46Dz6>JlpvSGsr2@1UM29a3VFE9sFElyy^C`cShe~-|q zUGLrN^!Rg-I=BFXsnP(RUq!Pqk|Bwk072!|%Zj*&=m;KSOW=KFiiTo%ACnNW} zHD@S#)asUA9=4rheq(LiJFx+`;diM^3~fq_uNI$3hWjP(4_R-&>oz|{1#)CmTF(oo z9JtbqJ57IG{si|*V{L5S@nA^CGJ|kLY49)O+>us>5Jd-2MIss7^P%lY5+ab@RjK@= ziPa5EVHzV8)le{K{5oSzbpSiZm@Hav-B$5AGx3rPJs8H08?2NoeBL?bbAco%ODO6wEysGly$qPg&;p`FYV z1KT<)Z&J=5U@gcux}h1077vw;wjhHd%&GYAH#U{{T#tv(&kc{H<(<6I$?N@l_{PYi zoJ`-fZ$gi41FF(o-*bI(+`s~9cwvq1()42kChUE*{W)$Kmm;<&aPfPXF;M3ha$f)J z8r>kZz-Is<+~0qZhR4Ayk1oq(kAlQl?Yc{rZ*G=*y*a{KLs4XkV>!48B3&Y8rbLhR z=Ga^7YZR$;_n`+0H<4rwnz9w~Ewp6Gx<3^suzz?+mzS1*)4g0`bsx^wwhyeyRJ-#bI9Hkl06-~1h2;&`+!L5Rfld(QP+ zYc9R65+{ltbcA9T$Yu_|bohDQJFWru;J97|GY$STTstE#AH<>~4IHlV-$%oemsS3p zUgimvqhF>kvartGaXbeVAC7Hhuf=4Zf}AxOA!EGy-ol3r6*f#>`>TRA83Tr-gWR%- z>xmjdq38>rbOO(2Q2(%^p*B_KeECGkAY1(cS6|s96NRhM5BOC+-*PxYto}fN^Ls@8 zaIDgje2R+i>%I~TV?4(_90+jGXE(+}axDWPLA4$HFJ$0y8fdp?)9lJn>2K_Lm^<)Q z{oRpq8oZ5RgA~P4i$zvdC+^&WchN7Gp^o`b!@H@ts?Ofy3awNzE7T2k{0#>W;%bxK zZ9zVKNjAiT@!=<*m7knCy~Z0AOrbR#6HI~h045E%cBF=l{-=gXEnhA%#XY_B^tAT) z^BENMCfXwDxyGUpHT}WoL{m2sTULgWkD=%h%z}6+*~AaMbA%+0)?;Rv=S@%6z70Oc zk3GjqXkT-b8Zf903d1^|x{tn;^n|1RnrUf~(bLN1Znc9nInZj_%u5?@HL>P_vc>IC zgOt!QyA%2(>Qy~V7`;^C@J;C+c`OaS$Q0Fp%hPqh`%rh-C6g>YCb&!nL~aYitHFdh z&VPE5-MUl zBk4tZ6R!KmT9B=hG}2~~DvZQ2elLPl&PK*^qx(* zf%F`lyx~9;ztVO-=;{a2U_{q=(pxc*@dn$iv=~DIJN1L?5Ac6S#&hEp^Z}&yH&2G5 z!|H{HBty}(Nj z-3V{t_q~L70uXK$bhFR<8YD^y>X_G2{Y1VVG03~RI5)IVpAg*z{e z@-^UIo^%;iUTb*JAoV4jERFg{!(HHLZ-thB-?GTmNgB$FK8zY}2&FMOb>{wed$Qy~ zKE;Ybu`P&Ab*k|h$fv1r8B>e7QY@(ZxW|VWM^0w?5ls3A3N1OMtmZUX-QHd%hP$2% z!_u$YbJS3*@J4+#R1Tj6ch|GQpv^mhvLjm*CO4-oI=CxIho`%9gqO;!)T*%e@Vzdi zE?K;|61=l`#C!A*|Hb`Ak2k|+b@)c6uT+C07xHUDIjuxf@wXE0jQPuipl6@Ip{eJ}4~ddlG!^@p zEFR9w@rvTgt?s%^H=?4O`ExO9QI4M!TN2@~dc-fxRLnyaS4b~^BGj#>uz^CkPUVT) z91uANzeoCwfdb~t&11`N*QKFbd^UhCv$chvxh&c#Y3M~o~(S)Tch;t56Dm@Mk$VB7f@ z?w)~T7I*1dHB1$gPa9Pp!$7e+2mx9*iEUEdI>(3&^u?O|-sfEokRJw{h2{pHSvD4} z5NIqN>vgZ9=PoPQqkn!e%dqjHTd*6`@Eh+} zZbTos$`~vzmsb8qx{CPQSNCJl+U~lZYEnca1_Mn7fro{?MyD=nRW4asyQuDwy4lUM zRyK0MQ4*l!L%ku;O(o5$eeK5rSA>qDYgsJ3O)pi>qFByMqR6)Ht!npPmD?5Tb+0CW z1v87GA(y7H@S81C&vkxH-bRLsWX>N!dK#EX$OSUNI}N{d_~a4Ze0%nz+?XWNoY=&W zmQ420zh8~TF0e}xEm4 zWGGxJ0fi-c6Q<&QMz-M%xW3`Mm;Z;b?*OMdZ2!0SmXVPY8Ih5)38e@rn+`&xvW_h> zBP63TLw02)8Ry8}LX^zRLv~h3S^e*?-uL%=fA9NV*Z;a)E~k^@obUH}?&rQg#c zqmf@WeYO@qz|0ciSE;U#EF8fw`~#-ovDq=3NfRK@fC>NT^$TsHH+*u`y`ZL9IXi=q zfU4o#rV1oUKVU`(>#qF#1-H_79d9}oUY>8EdWQ+(u-aS3npVcBj_2hY=4*sSbK3y! z$Ms}EU;QG{aYLI0rWsthUCh;@_OZJnMz2xk(2&`A+fRgg9yik&#K7p(-|ja0bwP{M zwX!!HQ&7dFxR%zHrrsv19347Pbp3-6T<|OzIGWIRSi1mz!U!7a_SAqY|0xr{W;+a@ zwE+RoJDB1gAvh|(zxjofNW41fVvz5C7>~cnzpQE@NUFCK--}0yy7b#noV6dg5sjt?;{rwHM9x39<=Ox1pXx<+YBamY-G ztubiJam%b7{(%&pPWICL?9v%oc9^MIG!x6xR;+>ZreAay`g6=wj5ujsFT+5--3eW5 z3!T3X)gRk>TB83-hj3I&I!}m57eAoR{OzNZ`>61v#E9RJ^{Yz#cIn$qQ7|Q0{uSNmI&(WU0Z7WuNGgRzqhC@Aj-T_FJ+DHApKm0kW)knJyhH(69mPP7 zjAmO=j_y(PTf?OR$;Cn|?RfUEx3Jbzg-fmB^d2Ak1;@S?6a!mbP~gt@g@HeG@T8Z7 z3)ru}MihY6@<+@YWTbOfv5ahQ(|pLlaCV+ehwrgF2mR_8obo( zqUmo&6Rw71?DJ<|c;D&1l1T7I5cg)%Cm477FipePQsP-xQXoT9X^)vZPk|jMf`YoV zjPI!U!%r?EVz&;r$CNew0L>@~YFya#olTilyNt4J$C2R*$CO$|K8er=x%Yqn*de10 zA`Uh-88nARpQ6;ivO1$qoK4SeEQ*3i(SPSU&hSlPSK66G*d6Y{tWM>Qd9k^d zXjxCF;Ehy|y{v=W>p2F$tdCT`AE5e8&Ov*RuvvINVRE{N0Jg$if?ojf?Ku0ndE`QV zb2uh48f}rIeTa4N9{Y3$q?QQ^D>%NQ0i{2C8^~z!oO0SX-+2hJ7<*c7?EQss7*0ZE zk#yW|0Z<0NI~T-^sqn0q%%(4{Lw_LGqoK~b<1EqW#RgiUNk45`s~R5mq0;E;YoRnD zN6uS&5FrO1ey1sj!sxTQNRuD?_RY~SC?u>)eiHU%dLL_X6MCTzWy) z$I}l*rsa2~7IL^;YmK^Pp&yx!6TeuzBvg#xED;Ke;TpI_and2*@!D$r-YhGY!us9J~-l$YK zjV;zN>hK5AAaC;{9Du}%kzYxm=wCYoGc=QDQxB88J z&h8CIiy>u1@jUqkDcqWe1wcGCG>3-VY zzF`$T2q|R;;o_Q=ywkA!5#;}-T}eLQCd%0bO>Bi2LK+)Zmx{ecUQ51Og7S05AYzvv z$?&M`Qgv^j=EI1WzLqa_87ECkp$^WuUo+0baOp$CIjTe4?j9rk=d(H7DsQO-884x- zP?*p%{$HI>%}J;rbVFsJzWQ@?YBc97~O>Lg0wbqr(i>B$k zkVF`EFgq>tGk22Y=kZK3&@CGUXSS5}Vzrg^%mrCYLIa&5n7aLnhzg;yHYhYX2`5k@ zEY$hz@^bqTox8%vw;s)OlAgZ{ccmjJoW4tV-#nBK?IwW zp?HR}uGmBE_}kBALeOdQ9sr(RjFgq=IqM8zf|esE6b-FK-!ClU{4NqyH*i-UPr3=5 zhnpQsv4P7p^sI*%&00S0^W`NBR?cqK#Fbl|`)%_ql*6rxN|Ao5lA-5;x0nt5hFdCv;E&uy$bd>RM@@xVlol91JvHexksETEq|>&0WKn=%>Y&)JL>ceScBI29r?wu z@eI9O?cOCpS>>sKT-EB6qwhLX{`muEIlT8oIe7A(KKvl__lNi->|x>)G3+KrN%9DO z_rObCd51?mXF< zyl<*C7Ly1qj<^^7y8sk1jel2V44qH7C z)2aQoAndHpyPLa$N5=$YE+NE~dVcfCUrO5KcfY73t)j}O2cUOUuKsk=8}UIb{ah@h zHjDOxTxyU))(5_Y2B0E#TsfL%HWiXi<_gNR9A{1Bl(~E9uBlnSP*KAfURr+vSoa35 z{J{;W_~Vu!r2P7!=X|`JdCSF)OvrLuJ2G8sJoCHmu(Ns|%PWOGCCPKRt%SpcK$Ch* z{%uN}UA|fmal;{ca`juP22sNa1{NpBBvb)Xh6(~gym;}bMN-KSKiqrsaf@;f{a{K8 zL0A=8H~l$CE-=u+{d(b1&5;E-S?UGlw?q8!`^)<92xVJxH4v%E$E2(Y2w$i}m9Ag1 zYf6oMPV?;a&DJ%UWOAQ>a0PmAsIlGhOQ(`$U92zdZa_bg#CQ?oTka{N?36&^7Q<4Q zz76H^fH0m_pPxe=SR9vTQenvN3FxM8fHNA9Bl6{Z_-kx5)I3jo;u}S&GdA)8s6S@k zXK*7|(;<&!{|N%0CBG~VML!T4ebhF5NFICl$)%AHX`qBhzrGGZ7Z{Ph4IQ4yv8eIY zlG|!@Uh_fowQ6Lmenc# znW=NvQ(|)1?qh@Ax}&vzzQYIoo~9M|lMll(L4#VZX1vXc8A*OJN8?XbU0S0Zb6%qz zn(xCedGdNFLrz`CY1EEiK^U0&@bqI!?>j+D4zEV5TwMEe`KwmZ*K!*u>mlL(L_X6Y zj5kUj*Ti|K(4K&05GEF@C040+DOD*h8tpQPB*uA?A_71%-vD~M9$I%JatGI`2*D0Y z!PJaD@uy5BttONK-*;U@nZIK`Kh{;e+U&I*IN6N#QEk^)?ho<2?(r(#s@p|1f;tek0 z*#r5;qNXr-uiP1YS;$)K^9nqAoJ*y@mvDnm#*;ed?9G1 zy+Ho+T4T{iI7(FhqA=tb9p0b}CIsuM77#HmqPYtdkh$N^CS$dP@67?uuM4OGFX=!9 z;{qec1!yQ;`}H8+bBDr`xwQ7OlFw$WX2<%i6-BcA{dotHpIjn-k28SUA=u+yav?ka zeWQ)O4W`_-Tg?2D0Tg|g)-vkr?{^jNdBppp(Knui+Y-$fK;&SQdpXpTtvFaL(1L2`V>})Q)gC@L(OXw1X3eIEl)k8_EA6)WIM~|CfvPIG5dW}WlNFhr)ob>Aw zK7lfS9h*0;0C9{w4lf6%Kl^Q_6v)&mHIABvG#1e`YFq2W`AK;4LF6}tB_Bv}zJ=)= zjbkGO_>OkvF|9XYgHT+61EGq-~P zwM9J*Zn;ia{%+4hZzxQZ+FezRwwE2lgp}-Cyf!L&uX&ugq<1b{dv{Owray{gV7ls` zWpu}H044l@yG-R0z)!q^#u=)y@4b^<18=`68JTwOoa~(N!5;Ir;3fGKHjLS{L@IHx{8D_fC3)1V0DBjV#86hCHaClVW zTUCUD*Q0jMXLE;~=|j?Q8a%6oS`(64-(s)AUN7?TSjZ1SS54x|ErWbnl{rz@-fJJN z)Rt2LR&$^^g6!_3z)eb;%I}gV5y?WM%hIPzxHT`VhyXT=Uli7FB9e7lwyu_J@}_pA z+twPDajDChHaf0&G(B)mRgrD#9z#zktT_k;N^#JK2V&Ac*(q7UCo0z{;g$$2*4tbg zN&dLJIAWZu33=A7Zb+YB}|5%wm2eg{=O?l;M@H)CEt952u&CIhUW2_UDp?3 zjs*P$kj~!YlVm%U5ntX$q9%W`BTqK zv5}9A0Ulv5)_!Oz-w8uj`}jw9PNZFN89PC7_BQ6B7Our0;xbCho)KBd3;Z*h0Gd(f z{OdvnN^c7a(sNsk@GYpPK>7xvkE!$Fy@6|CZ1vv+A&dVtaT7tg2*V7w|vM6jlK{}B|Xy8nEN$VheVJSRW zRSVcg^}#8_{J1i3qfO%awWB=6b+gnmY0UuF`!Rsl&eo-%5zM)mVVSQ+g*^m<0DVXx zqvdQ*u^(t>1yo7(RLw=y=-q+p%KLkt+kX5US?V2O9~674A~o~)OF7#3_x0T0p%>`j zj^^TVQtq$0&bfy}bkbGF(&3F3ByDY`?2A7@seiFDX@>xBRK5rb&vRtYS0oK-u_@{q zrlqs4v!-?(BTEASUpMLo^$izY$0mrT;Bn=x=c6jkLs^jxHTt0bFdN4W$vq$mRtI$x z464zELzc0cY*r<5=Vy&UN20hOj4aQXPN3hX#Tx-JI|I}N;JyjJJ`ouWml})b73#$! zt+V(Z`^j>x5m$2-ZXO-l2=dR-R0_Vb)dXgkJbys02$Z>e^Oiozbl@$c-~S6WHjPww zfY(8@-@NY=0V;C!-EYxy_FqW8Ryc|@rI-oaY<>I$g8DN}8jv^@Cgs0d6oJ6wVF%@2 zZor>|U_wI{VFRJEUYH1jf;21sr2flxsOP9Y&XF*|%2LDis|aXA+?H8zie6$<%_#R# z9n4U@V47|5$#J;4GCWsK!JNqM#l3{HVVI@q7@IU7#*cvhd$1VKe=SEt_lv#Xw?w7~ za@`jsC66HK*f*)a$^--fXh;Kn;+wJepmIzto^HKmKRw`5*X+lP1brkq`Sdok%qaLk z6fND!!9Q?z!);fJI4>P6MZq9#> zVC!zEJS=EtCJ9^2>BI@uaZ)-8PNMXy(IL2*M4065I@8&yy_Myl3~E?kz|iII0qy|$ zmNfsIMj)nKUtl7G?v9LIGe<9YebKqP!G=+Li5!6`9E_YL$Bg-gZYw#}P_H#H4j!)- zf_E$LZ*Bz@y?u1kK-l)%U1>Lse+MfU_leXP?dB#1zc9X>63Q&xq_%&jETP#|jCsRW2=SFO(b!L9DcIX$c6Zu} z%6~l3JdKEC5Ft|doT|K2vTan6alYB*hx7|TSaS6pUh9^i?hhvz)S!3-A8lf>31hRs zEx(kVi`-b$sC?|!E@v5c;WVgxlk%AS7G8{twTb2k-vlJtr~K}d`WLRF)|NeDzOSU= zaM;fvKAz75h>%MD0I)yBU0Kr!=D+Thd${ImjGk3zs8KrVH{^*h0%_qw{#9Bcbs?5t}w}6~WRJqOylH``yFq#%c(Jf(R3!h&3N) zaEgM`2sBDFl;i(~zxaVb?}iex7506}wEWW&~)C^!{a zls=C}x88|_{;s!w^2PtS13pvMyIsq|sL{poqAJhUWSIa9r>3`Ww=w=4(%N!Pd2xQ2 zKty*%XJ>2hr~?@B+po@SNX>fE{uR7YBA_v~XxxPvQ{k4iujPm;#Srvu1bEgL)OcLz z+)N5jY>_D(#m}Zr_WY)FrQ=*pSZzs^|vg*H=XDA*k34mbAchc z+i37OhzRBLcO^plBK!S*LCIjc8tA$xSC;N`EOcXuW=pXHAVf8y zq3ZU4#NS6dRrYhKxbm+_;$#`;7hvwEcWtB;Y>yCp@%j&FY&+cU*-d3#jPy=-wOn&< zg|s#SNWVd#+SvO@I3b)7auJteL|Y?oQ(LS3%#Cl*HYF)ubyLYGE9&`jqc2HDnF0? z;;~q7vAy!nZBQ(^*uoN2DW9&a7Y8vqJW^JFJ3MzI&((GzI}|<9UMK@EFhR_lCVv5E zsLrYigM?CeuCy=6cgBm0@0Vlj>$KA$Vd5dbQ1x@!#)KJUs5hM@16hi@9g=kLM)&bX z`TM>Q1Uoz8MfA#u#$QPI_%1- zbUf!$*O%QMkW#wq4>Fq>W0b6_-=R2}C*1SZJSLj=pEimzLzgrCSDFSrp_tJ|x8smb zvCDEZIyu7bB`!a#369mvMUVt*BB>83O|W7h5tP|{KP9h;V{rl4sk8V69Khl~p7?O% zS^Wbq$infe;>ACDUKwbIbfvp+R}p9kp5($-!0owoa|VifBMHGmlExxDl;5^CaDlMB zr;=3hP@S7%*yozX)b#idrODxaV^9U6=pM0oXk2;B<^c~tIU{J8b?BWSm{z#;yVZ%C zC=1{8a4F7@fvF@(kRX$b3)^~?y_nQ(*1l_*gT1(HpEh1t1X0^TSYx~MubD7}isx(i69595s-Tm{J}yoa*CE^S&KHA6aBqfJ9A)pj zFOHfj+&^`_y4`cD@G9f{m#P?6oi3kg+W34B%2v=nTI{!{@DE@8S`MJd$lAtYB+2=^ z-zc%3JAIEvi&&!rYIZk2M+Z1}`S5wE{=&_rDR{8TT8bH+d|lxO_11_v;oPAA{;vJp z;GHk8hTpu{I!UxVQl4lvCt+w^{or3AAL=*+0n&oG-W@_z}Q%&%X3qinDC&2lt5^_dm4sLPsyta-VpIac~fP zsqT^AJ#}X|E7xJ~c6Om3)SEBw85irC`?#+jS2!)}GJGecHgd&|Tkf%~JA<`*OwB zHhzbU3!B8z=#xHp?c~nd1uo_KIZ4ATkAv55$w634AVO52VA!GgPwo{#?@hil&yQ9< zLwT(8$~rmjcK8#!R$oF?oJSCC0T3P;;Cq#Q404s={}myLP|H85ie&~V*N#`jLrJGb zZCD_izgiN_vH*jPM|=jOWgn1gsKwMSy(k1N8i!fp;~(`A!CILN?Ji2)o&QBNMYS>8 zU4HGRld&#fK>RS{0*U0^C9&e8=kuE{cnW{SUw^+npBaMg_o((B)VW0=;U`pfdsvSW z+YOjpIgo&#-96;$_8&%ZoWu{bz++QNtkH}j{TBih%yKL&PTdJOOnzS$P>=mQTys=o z_wur)b!r(7Tr`&w`MaWn<)k<>y8+Ir&vyVa;c21?~3cGBw`F zHd&6jQ8ZejVvJZyf>(c^VFIK!#J&~lOCUntCpef#@{>bO`=8e}i=@wEao|ZP^>L)| zA5r>0o-p^@6BZ984Xw@A1VpE&|FYQ~!8+f>zL6Y;b|$C1i6-CQzC-S>noJ4B7uSO6 z=%^u%)yt8HXRQ-)(D5PH|$N`~W8;XW+5nOBFvpdL7b7@x9K<5cC&7ZFA|rir@z%Ad7hSUsqa; zD|8mO0!!uc#|XclZi4v2Pa1H)?;y;>^A&2@FhpS=bsfP+UfyduDkv#Ie@H@qtkS*% z{3j)r?&RDnmuV1woOO2Kfg}t7!c_@KaD2UoJ=|wH${lu3!p@CBac;vZg+2#661-Y;WmdFbR>Y}{H)Lc@V67hUtP4!!^)-;4omw_rek4CciW0WzY>1&r*^Hnw2aGrp^h9) zhkMm8j7}3LWdc(L_zDac1rmZufNG-}h%=vnr0UJVw{aWs!^QR3FN&^D+UKbFJVYBH z>Z7^DGqMkV>PAyzeSY@2gvz-a$RH0cMfXLci-nIfM&2Xhi@!z}jh?pfGn4~x$o9GS zRjE(L;2=)sLwHEh9si>&$Tf4B^gi~O3JZ1#SaOeE8bFHtsxH&8Vf)`e~$kz=${6V(k_(20l%|70T9~``d=k9 zX8Xp__4J4&6Hxwsdv59Aiq03)=Sn{)EZ^m-x2=<{FJTtWP&gS zh9bi_s|VGWfx#VTXBg0@#7amwM>AaqZydqgt0&+#Z7VX4N9=@zYh+&V1*s`UDT3xK zc3>Pu+dbX97QfD(D~sZ(*Ym+L;D#lp_6Z;n`Ii@VvC%GY$gTiBlSI<5vg% z3P*V7njQGBZ4>=l6_7(I9rqvS#%YqO z*bhnUZ$cT&*NhN(YZ_n9}*7YcEJU*tea0=6JX#4@D%x@VtPrt!UQSJZEd-a0p z6ld9a@Z24P>{1Mzh~IyJN8|4gmq4sAYzy@Hzto|SAI$!RW37Ltrr46e%LyV=cQ!5X z%|7~hne@jLh1ks9pMdn~;?)U|J#K>UJGK5!ECWIhKoEM0k`lH18vG>F+e+FNI8lFh zpRxChkR9`jnc?aWxq(Cr4o0VspYoWtzbVp>5P)LuN;Sq06nnR<-85%948QeO8$_JB z1-b0A8hztLF>|2K>OhucC;8_(@8Lmk9!ff0q`Y#U2cjONrZI>+xLUr{>OFG+(hw!* zd??lMTdmPB0;YBw?NdfLkIi}AhO^B>Q!IN4NI?}Rq|5t09F3EL9`(z((2YsZXv7*4 za$NyM06%BP&^mj2^F-6<=(C%I-BeMWQbyfWBIQlNnRju+ibNQ?JN@tCp%+sIw;Dw& z;Nl2KnB)sb#&n11k z9nymP9UMpHxr9?v$JFEuYV*>BFE_($y{)LsiE_2vS5qi?UKE8^-}CFk%;2`Z%;u2I zed9QNm@vC8-|kr7Z|S7XQCF*k$&a=mqTO)=zI!G&(c&rGv!zvNsaI2IAU&!o0@+++ z9UKw`&hRbrevXAYjx>n>(k2N0;T-atUEx416Kiu&A{=16?gGYq96vDulnww}@`vub zT?CBwn=O$#kCXatMuoMml$`(#PpbU8b@5R2@K8a+$SdvEX6sP&&(T!o`48X0IX%!xg@R|Y;U9*PROZqrDnRvRXB(e`b`uR67rYk0 z89W;BXWyq6YWeJLvlZLDgYRHV+r_*)WeV~$<(-?KGE{ZjiZaNU_9v|ibif7C$S(c} z1OyjrER}GcyoN_poqm4DQ%ncDcLfyaX20BA?AMQKA3a%W*CT!7xV?~C1`Ki}A{_fZ ztPzjP{&ZhQLW_Vdk0F-VkoUzPWQO(s6q~;5;n7h96*DyKajGLM)Rp%H)-9_E@fz#a zSf#7ujfQ+Bel7R7Yj3v`?U}32oq>ts^k>41jiO}vjyxp42wwm_XW1hi&_{mo z8~*XU!?r5RR?}%9&4Bj#om~sd7=Cr+&<1UqdEP(2dGH3PoPb~i@o4)ex3JrG$$;bU zehyI?yaPq?JonX7!0&P?V++_WqrRLzEskg9z_VIca*}>t0y+Kn7dgsRiFGhwX$Emd zd?~J4c^?P^b;W%94z)LH!EZ`5qaLuigAp-exC7^LC)glj@!}>lxq{`4QB<2!(1>pj zy2pyKC;a?c7i35gqsJY~_>C6{oYRDLD_tN7tR37Sf8ISX$nqEALdY|(5C3}6V*$J_ zEZGw7z*+UJ`9t_4{|g(qWVpHhWSk!;N>N;^C-!MW#z4XdI@ioJgaO@Z%1Pui&J6WS z0*9smZ0?rB15AyKmg|JK6-^Cgzf`GcGU{af_E9azbEKFRFB`IRFVqQx^Uah%%B4njUa}HmO7oalw-W9c$l(59{lQ z%;%55g%+QrFn5bF2po0l57eQ%KtaXrm@y@iqOz_wfqi|JfJ6r(tcmv0i^&UAS{&b`_@X)sbVig zSNQAR)`E)0M>rG)PDNX8WYP;4@I>$LY(H~0$TtFEVkWUcJV4LS-YY{(pt&9Zgu=vB zIPz2?H&^L4M-`HaNl4Cpk z36%AxN18WK|BK$DM&I98Q}gfX5<)89-naTt6D{BgjVBstcr{X0SMi4`sGc1Qp~pQ}ciwd&D~M z{b^4zEzx3n!R|U}&3|N??2+IHECG=VgbX`!(%euLC$(t?982txo!i2JhOe_uJqHT~ ztH&+C?I6lvG1Mm+L=5v!@LhWR$v0+oC2>k4ApC5&5YiPl)xGz!d@gTom@!W3id_AV zZHb*vHXqoK{+Vq81ydC)K>}C0bsLK`^3|%tZ~YIq1>ol?#*GQUm3oHE0pfMym{q1Ui4Wjwfcykg-?i@)~ zJMe>DcKn%kVO6l4i;b6%3H5)!+D`>VcBH2FkwI(Uls?ztir72?qY4+-RXDz#IQATZ zRbJk-cES%RAFR`x;xL)Vh5{>`M=Gw+OEg1qsq$6zqd1)1l~uCocO$QVNP+lKCinzx5n8r{ zgkG^!-DnD~7S=YG&SHaz42Y8pL52PKx8pzZ$+JGbVGBSMbmFnnL)x^FIGMVkDq>V<<%o^z%GtAui z%9Zy^h}?0f^y44)#L~+t9#04;WB=tVB$;5^A~^~o4a;n4kfS(j(82z0Cyahmujz(? zxP0K%5-mFbY0C_s+K!KdoizH@r2Ch>gw9>eG^?IFu4JxDg z{J&pmkQqwLZei6b)k9v5by6n4<1(JG|;QPe-EPl>%AX|b#WkDUg%@I z;r}~VC!OLJ?DvIsEA-|6cvoCRhdGB_+;5pBN|5JWz15YJx&1{e$pieM9a`cwIdeTJ zGFP3dmMaSF8oB>t9WkMTv>8FR)nUN-00#!i;31LW{+HTq&D9}j)I)KxPvZH{OAP-)#Q<+c_?m8lANYhi< zdJS=F$a{Vlf-Yrg0vGT`1oRBj5&wR>G%_^)UK*B&bZQ&sAf&O(8vRUt5b=-s?3fN{ z37-Q~j(ZD?#g+D9jBzoF0GUa>pY~rq9DKeL>XXPkzDLps=sl__R|{4FIe!9^ultbx zPf=puioj+6eto7V0QSk2xdW_?m4x8k2T1m5Bf!-P5O3fko^F3grRlxO>fDQA4l*rIU&86 zkHH8)p{Ec-I$(%m&%75XQgqjd|IZFYcB4u=MG|t_v%Dh?`gkS1{)1rpDWulT0ayKx z()4|8X9m??L_NqCqX<5Ju`6{BY#;1;5Yr})a4>?Y(TnLv&*lWh0m zv%>bbXIDGG$IdqP8Q9YfpzLy7XF7hsV$y`c;@KN(c$hGmfSi<9Ii($v9ERSi1{{-j ze?96s;<&Q`&2&$$R&PWfbp83yzpH@~BGGPvwn0>y^rhSblqlN^PzKFFf0%d(8B}^F z-u-LL`JbP2bm|QVM7CH-1FpbApHLqjfVSK3iqtEW|1B!QL+QU)$ToZ1g#16Q-(f)e zMnI@fSmKN&5vF)h;a(y&V=)W%$FRD(l{oud-k3f?90+zyoGaF7vi(WK}W_wq< z{I|PK$ka|jsE@SOlI&F)rTFjf=O4Q+_);Yd8mH^}1!>sLHvejlKww1r+QE`uA-T@X$d+B40- z0KqsYQ#2!(_-)__`~h7&IuN%sOa>3AF?t3ic_)9O8870}T~^t@y#XDFXP_edX(l+& zoO1RKFQR!Ssau5}E4YtW;!Q_sTf0>1EI_&Cvk1nIna}DxQKq~<$`SY3J6o+gLvJ%D ze+|F)C~z3BHf@dJ5r@CIVJ6tlyf05)on+>_TloqoM8~?eWMd z{SpO1?YTg<I(c^nM4{f3`x)01JC*@xwGDdvf>?QXxQApg zr?lrBTA2-BtK>9_%douip4&>6yjyOL>*#4~wcg#3i6d5vk#Ez8f9(%}qi+9H$Ob{r zd8BTd{LRvk@s&dTrXShU`urv4p?7}<(UybDvkNjObJa_Pdp%_?JfBP z$7?5qJm=qw1;sXS?npwjdu|bNoizVbOM_C1o;RN19pCrd9I=`5P4aGA33xZSKeV;C zckIachqp`p1&RL7N#TQ_0yz#b&pqqn{WP{XdvD3=v5ZCzPHHOWw~xJO>t+(rIbe!& z8l`NcJi7ePUI5CjXyLfnS?I3k3o(P@(P11AHO5}ed zB=O}8c#pl+_uLjnu*Iwn$Jc@p_z!6WVwd8K!;>NTJ;{>Kq0kJJj7w4lpUzU0AFRg& zXn@R*>SGg$nFI`n^!azwIIq{WAs!)x97h z!Xvf5@dnBF96Rkfc36Vts*hZNtQo*&QdUtA8IHQNarf2*{2}_1CeH9<3_(tI~h4d$;d>d!kO_xGo$<&yz6X zRCNXXB(qWq*S<9R(AoU3_~sQBvd*<;o$$T9)81V9Rp=I1eW|{rc#Bi*@7el4;WQg^ zfrR9sb$W_)W`;&ZxcSUIa8F&lxb``MaG#;Vji4tzU~ih|*~?0&G5O#9#s2Y|Km1Rz zx4IFu?Lx2nlWEpnO?LY&6WBf24 zG#3nte|+O%y6_@y5;_vs+}f2Fz1^d9`>J%?WMexg`EB9lpIi0a1&Z;WuUu(`x@!fP z1%>iy4iNUp@+IEuFsp^r4qKVCIi67CnPrE#nJ-O>@$)mj9eLvV4tkZ-x zO3c=~(06mXc0?1G)sU=O^-!>rQ=^fclbXXBqwP+6m`h#M zytrpN@*k27CRf1|y;-#e^lo1LCMw`G3(~!@y{5Y&G?+kal)cEJ(skzia+DxUvdfKB zgjP8E6DmEecz5cgk?d@Vt< zB8Az8lq1Q4JD8G0Dx>3KP$bE*vbWLMvIj6`hwrw%B37&>tLIODp1wLvr!Bk9IA;9n z@_Gn5PtvU-rE9{f>EQ>EOYP2QSu_^;@9%s_KiCwkp&{C0*S)tksaiRo6s}anAZU@)Vr;vjS)6iRzc(8&hZpC4M^+LAwBJt^0x#Sru61js z!8g#2UN>geNyiYzL5)6>7Bg-RMuM|wV ziLshV)2w=cNqyD3Vo*%@VZ~X}g-8}V75Z8~_6qSzk+*VSQlZg6c2cm>|> zPL*>VH1}Gd76>uJ;LkteIP&_yd7y?<0rvT)0^(X=ev-b=+2>~U4Od7bw*Q3Jp9jZh+(ILG!TCr z>8%!UZpnF4IY^*x=nco9Qi<719z0PH(jX^EF%T5x?Iz5**+_2|hoqX4j$hC2%Z2}e zc-8)`roG3X62#;!r;_ax2YvjnQZLC7IB8t{xn1|ioDZ?u$Hwg@OjO@oqTiLnEEQop z+Mn=kIUN@YwnI_)rp*lx?bA+eOQaJ=cw1vAdIKz*Imwt%A2k`Yl6r#fZOksP-JN_? zwn(9OT*CkBomUHG3*Ds*-Or$!BW0|!OM&!QQKa)J*c@#ytGmh+GE+1vq2ebD!w0RJ zm8qsojLkjb?{9uq-%;=vnSka`J1vZ4c2l8@36z?YU)`=&KxFGsi1#GNvtP~qdwdqd z@j2QPhd>h55Z^xwgGnQwTLo*b}S|!3vXTf{HV5 zNhEf-2-(8ZF~{44SljM=(87_ni0PTvuaohTJ`Q&YE*rZ1IHVy)^hnogU*5BW$A2cD zk~XmE#Y2}s^i{8z-k(e|sG$c(f`u?%!ES_)+@7efk&BDg?XD;&asN5qc4{_T<=SWH zPJ-NJ)xh9QUX5I0JTh0zC1hL+}Iq56iaFJ^gCcXDmzio2Q$~onfl+f56tvmSY zvtmUf*4tF!oh@CAbNlX+pxwp1bObwAvh{1L2DhxU#Syr#_0S8#8_m!qGcHnbCB~bc zFGM!gws^+TDAuUpp^9Clz!&ph0{m|@-Skp8I=--Z&%v*vF6;@GE!(E}g2mF;RMxZO zL)%ktn|8(7PoO^L-#lye?1r!h=`zQQQ>$-VTZ3B_V72MC^#id@I-+{??Cn^GuVs0! z4GTZgi#RtkGrFki?liPxNEbeg-te<)_b+XkXD$cS15$0tZ&_0!#917j2PMJ z)p|@o$8i4mwHRG7Z$>6G>U$&gshp2h-=1o1I>>%fiF1c^>5i1}rM5|;hq^-=CE>xp zC+=@V9em&O`aP4_35L4Dy7T>1$#yq7zRrA}qItu5Ql3d)N|FICXQI$B881cjt}GZ$M|*ClZm2-wZ|L2<5WV ztDTIzg<6|VQ~i7;G$&P)aTN(~IIrChW}R4&*K0!mz^&5?UMr)oF`q?-Oh<3FnH$HR zWAjoD#?aN--P?vE8-J|rl;iAtd>#Dbl-L^}j1FWu`UMDYee?OhW zNcI$;=8&2JRk%-v@Qag-B(7UXAn!)-8{|UgFM{$KV?yHMMe7^S z&V>TFZD@m_O{a4vF9_ET1(&H}rp`A^nCM>o{zG-gA`T;>i=IB+B+u|%#WpJV>^Tj) zDKUoI_%I2*lniIfC5ncK#KZjlM?Eq9d_VpXS*DpoL(}PFPiwd;trKZ`y_9o7iM;C- zI~z8`g^8JkuKO#gJd^Tw`-FZ&+sEJ#St~TSw8Gom04IE5BKw3yk9TrVslK3OePw~c zNVa?F!b6&q-((;4scGnj1lM_uc_a?b5}*FqSE_syGd^bj$V;~;xh3MBPr2flr?2Ce z)-v}I?p2O!N1VT-1zs$bq``9f012P_PQTyo&&yDbpO$;uQf%-2(z|VGBZG*ZdDXr6 zg6ceRoi|$|H<_P8vKDam*;h~u#SK*-pldA!4K=iX3m_%D(3>noA7um#1Vzrbi zCL1Wl>vX`c>X;XOHWCD`{gGC2ikH?iE#(wXoL{H6qs%$sM%3a%xHWMDCWzi%xm#V> zpq27AZc33ru#;xjABy|=a}CsHLJw}5%N_HXKRy;_!kTqzlhN$cS_bP9j&x3}8g)ta z;O^!f2bWX4+p81B`mdV1=@-4~x(TaoQekezxqw)aqm6Q0BNRU~!2s{q{L6#R8!I4L z4(-0=i$p>q)uXu>Wogd4@FXy`x@E|2XGv^cU|%7oYtuHXN_8ZiaZc(c#NB8lJ!A3v zN2fRx;7(5v;B}lgDD_x^TYbrR4EZ|jDJ1>unH%?BBC+y;-w?OJB(wz5AEEdJ%}rO! zO)_4E&T!SQo(k{RokT(74sm-gTiF=-yus6fWJF)yK9+B;O`@{28X3NxIx#(Ox94wj zoRCQ)E%3%RL7D9EgrNp~lnKKl39`Ad>6hNw6>2VX zQ_YGs*DXe2K{dtPX>s&=H%RbZi+4QvG4m1r;LQj2S@Qe1hp(EdWc^;;uG@dkCNREW z5w>Uj{mmf#`0F~{cd_cV^NwbdPF1^S{7WaXB6=_6>TZs1JoqsTE6?Sgot8tF`1pcZ zQ`*h)HyxA2`gAyB=v!yF^K+SV{wC)#xQ*E_PMUi`tA(>pX5?0<9_-GE2mIDrt_VHK zJ|yY4<6fi9esJcnjHIdQk$(6{#YH?}(hgB z48=+sGgRA@uf(5FA0X68bqlea(&IUm|JUAihBditYdQ#01wlF@NN-Y=-Yh6Z1Vp-s zphyWVAQA{&kYWR=B1jRWC@nyMNL5jKhtMLuNe!JlVV`}@K5;+y+4uMLU!LTf$$T?w z)~xlech=%x)>4~!Au&vj5;W{9;Ff@v^8o0|z0h+oM%wOT3}=sEUdlaJmxa+mga zR%F@%b-hABN$-cYN{R!XML9A_d6gM@687^R4mo7>KwX6^h31(Q7FaQ6(0VP8h`K)Z z%wCSPP|g{xccqbEC;%D2Dps1tH2y>MSVF^LAJpRDMhYaOB12gcCi>V6*rA^zgAy zZ`;4ad2*z&dTIBIv;n%zCqwjIk-L2)WOEvnBDexIng`L5e!y34{GSB7QPqr{P?tx+a@v++ONqKuM7Md~%4xoFbu2M9Y_<)XU4f0AoMsP5V%N@nqguU) zNH9Q@8j;&czmh*>ny#d`KQUNch?oxOEBl!i6~Hh|WH9DRe3r7GB<$T5gzFNP{d0p4 z%Ufm2dOreW=VCdxB($9G>NLUdHIRWY?{!Ej04se!`OFP_gzRYoQc1xp{o4D%Th)#@dRb>DP+F6Eg`H~$A$2K&r%Bv!MWV80Lg$}f4hq!2QGcL% zE1_Xp?wkTkfFl@^>p413PJJ?E$3~=`9BNal;0&T7b}6(iMJ#R(hH`a93@zO$Bz(Nd zX9x-8zn17gpR<-EE23LjRyaPp+N$~b?0L?sZB)d|Hwt#MDl#kmhLDDKeK`iaIOHpn z+?aPt1>{b|Whun*_EetBw{Ea3kiv7;%=nGOvU-dCsP#givW-m-)|w#Cmt@$70@hBX zwn%yt@w28}fcAc{`9|e-?1W1LbX;><@p*$=$~pV!z3nzoN&uR@cmz@^1aHTaNNJ`a zn01C3V<`zgvF@b>8XAI7yr&~LxtTebo?l%{eqoRJgi9y>5M;LoA&TBSb$yc3a$Z!R zDoD1H8XGBIBR`(SGv~(Hz#ztwmeA-!AVyQ{T{UBD%WJX>P?=K}(x=9a-(wPrKVpcU zfs27%3gq|u3Pe8>M<*QsA2vJWighTsatAKNfdge)9(ovZiAY_PQSnT@4e34YdgBM9 z_EMUSZrX7oeU@>&$EU1hW2MsWei()tHmClq5RmHZGS<;&^9lCpRXXN8Qj zt74v7P6SekwePL~RE83!gDc|DQQJWmfV-&ewW4)J^c$@XPFJ)XWOwRL+mUmWUw_l= zc`1#Xa0p8PU2NR82$@$QqZzyPItPX3pfOhyEqm?jrbNa}He%U)A2PI9O0AN`RE}<} zAoE_-%bFm$w7m}SZ0%7=)Bva8OuhaC%ldPlE})gMReE)(3oqwuM$IujF3;r#tpm}3 z9xCMRG8x{+;|3294sYC)QDhn!U}P))e&Ix)D|l@Xv(%X%cqP=x3Yyz{OQo!VU zhKO1q1)GC!G{J>z=%|OpGBCHr(8xz^-T%^Vbahev)4dk8BAoH|H0bpB`x(e1>hwUD|BH`+gFtxknOXhHaG-T&v`C> zY?K*z_z`H18sh?U(>M{+bm%TXEBZ1J&+NvqZfYvzt}5DB%#o_9a1PlAA8aGdx*7P% z`+=jxVi4)kB>+lC$AbKY++{lIYf8tb31I%?tU=SJh>hDQLRh2%sn}=NU5!&JFytOU z*!sXB`WnOrd8)nhNxVJ4m+iZvDd!S^h_i+4D0*3_)R3phjaVs&?|nKu02R0F<5Aga>b(~!H+O9# zHR1S$J>AA-BgTgHpgB6HHP%$213X?FZ= z#;K|6KrmWH7qM55{wB!sp30CW{HH`Xwex!P_LJhP`iDn^ET(Qw`zm!E?u1Cb;SlaA zcpeI%$fN4JJK(69r((Q|l9>k~RFRS==Lp~3aWz!?6hg!-2UYt?t}ej{rBuL5IkcGC zr|^N?j7S=qH-4`2sPD`9ND$0crkxja90Rd{YW#~{N)+4XIm z=BJijP`9-Vb$=%Eh}TdbRG6_PR-~_53#1A}kj}cQ3F`U)c3r8!XUCNEXpTb9K>7Tf zeTq7TpP$ING&|H@g|FWf0E0a&381QrD~c;hCQd*yljau&!f3eLZwz~!eOzFnhT)2H zA46cGyNK@n46@}dP+6L&VRjioD(vufRbSOtAqNsy+z!}`9uGAo8qx?aBIob!fJm=a zN*N$QbAz~`XB*AJH0azpfFe%B9HAfMUBCPoU}wRd8=V8$63N6kfHI>_go2sJ+JkxT zWc?ZgEDzK%)~JLoFQszKv;j98J~AuK1|qqM1Qq9xAt-=cr43%)E2xvDtF0fqY`%sL zdKX(K|G6Mi_O&ldkd7|F%g441&0e`k^a|$#a=rx2nU8mh4)n6n2@@%gSP#my<3f+$oOo zBXXzt$#^3Bc3W^R^DXb_hq#perezOKDU%iSBSW*lUP!uaE9;Z(P7USCag_^0oU#K9 zB{y)SSJ{*AxZm{FP>uf75nk5!9mcnTLB#RA@~aGYExgA=41^#3psQUh8=6>j9?Kd6 z64U+85Tzw{ip6!?b@t3_Nf%dWXk_)PVdQ{0?qx6}qS?B|x85Ubg_5%}dN^f~&$;s5uqo+uKx+WJmZG!OJhU zQbr@X$YwuLp*eYoINRGct^5l zTg$v}wfksDzxZ0kTsW`)l>BuF>4TM~g17ER(J@ptZL5YWcVIw^1zneB)(J-WS?eNO zy2$U2-nlqC_wI9OZl5dGSM9BE82mB-P1eVUYW@AULDVhCTfnzWPy{K-QhhZ+3RnB? z9$=Wh@v8ul9@0a7SI$P7`ywUks{DTlQY_8gb05Q04VZNVdLVD=t`VvvyPgZk9TfED z1|hRJR60GaCPjM{2lr367AKRrnw)FN@&-$_hcJ7?9dXM_bJ+Ie&KfRq?kW~;5*yEY ze;crI=CtbQxK{_`(>VjWY(ilg5@?8QP(O(uYoW-kl1pFXMDx}j)hkgG`mA&H0?r(y zyN7@lu@n}FV->}6vGZ99HF|sQD4{nM0^Etjq1BX#gC%HfSMk_P@ZLOdenee$EBb`z z`oVPnXwzE6h0uO#sO~f}TXny)Sy8%5d)L7Q$pBp zDS$a-pNGr&Z|O71gkC^bLFcX0E?hfh-Vr;uJrrsZf`cW%@QN#FFRr3fj zhVE<-qg+M&7e9s97i9^1Z3-TrRs~@t(%LqC*$4gH zfDIXb(1emEspELM49rM7Q0eFud&F&kJV&JHeRv9p+7!`wPXovaldu6EwvRr12PwO% z_r_`c!)sL4pU{Zw1({z}1}?V=V*1*uw$l>AJy)`=E??}H>r|;OUDm*lsQqg)x&hNZ zdtPq0zkD8n+wT;;Wpl%p0&x*S7K^5y^cazsz3zjZP|gZmAK+j1C>R$<{tVPDrSS63 zma_Z$LZAuIKJIG}+0)66Sk=Ad4sV>2QREmIU|=i$!q#ji1Z1sh)3W;EteQuEFW{Gu zw(8jk*^Daz;7(yW*HSQ{hDddi1yJBv2$#Y8-m#Q;{-us3Z`F_!B=4hnwjc{^ZAw^k9Fa=*4V-!+ zlWO=Fw@6@=NU-ph8hn{zQ{&U3n0HZ~4)NPLRF2C{p^ULczUu&pDsHOw7Eos1AV?NE z_trhgh*ulQ>%9rG$uoZ;F1TN$H&WrA?J?h*k6LwJIo{pm&9m_2HcEq-Qu`&!kJ>Xd zvtOB<0RpMIc*eHawEM&JoC5Ce!uN3i^4NJf=V5ucH6tmJF=D?_81&JS%V?T_q;0Sb zoqgO2zcCn#dzuOeS-43$OsB+Be=1~BIlx}{?bA>PPSQGxM;Bw+K#4R=v1GC@}a@aAbK6PeR#=df4i0G7`X7cFwUv=$71)w;pcy0oJ_(CtnOph61( z6(SMEP~p>tCmI!P`*gCey zD)l$&>V{G%SHiep?H@$I>Jjd zTx`#5W~uV$VMMZZOa;%&%ag6|<_ZpoH13{HQ8pT#Z9Q}LY)VUN+T!T)3qSiqW%s?^ z7e4FCWE0!+@)sw?k*fXE8{a<6WnqgiFto(g{N_AGo_PnjvMT>x%9;8 zk8_r+vS7sle!S=h=ilHW`2gj6>4%{2B^_yHSQ zE~QnzhIkWHJseR4X;6~Db)wsAfX=K79k6URxu;pa3p=4NZ38$@zDWS+UC-LcR+$jd zgKQRVO|SQuSUFAPIiz=aW9M12J>%Ut?1g-1-h`D!*{{q7bY}L7C|5ArpO36FeMCA5 zmc?>#y>Zo{4Dd&rWvxK!q|Midjns$x4EFMo`;#D%Kia&?%c)8_mHW}*K6VKCegDPQ z?%Ly8Uk>81rjNdrU7t-C*qX(%mo7AyNrnySrd({Z9Rnqc`jKFFoprAUM2DfNp6AQ$ zkVZZZ;?l#&^B;{vjzmoTPZ0y(kFNp4-l^7DE)kJMwte#eTswM@R1&{c>wT|T^^xdp z#h9q+t6f0MU;_=aB^Y5w4C&r8F`e^d6G3Ni_0P(DBwJyp>=Vrrv2XlrFE^`7e{Xbr z0+NYMW$|}{eEBY;h#0x`_{~9)yZ}#uz6_D1hz8bj?Jqe#>x?riDr3WaMiAruEo=Kn zb&7M46~eDMGL6~o@orxpj%1KQy=gzM*1TVOG&xMWZaX=SsQ3@l? zb0l1T>m5_z=vREa0NBFltE20#ogA!%-5ANecE%W==ABXn6-HZ{mbeLvkGVeVLQWZz zs}PP4SP_h{31;CnV8I=d8X{$*e31K_Lvq#rJ|F6yz!JJ_x9mnfm9681Pu%yo zKPE~}w#&D9lE+~6`dx|nF{AE zWrDPV$7G*uP&S<6Og|;e8U+K?k!z1UZ_j>zc2iEdW2H+^h3V6T^n90zC=56h%=VK) zXq$&YZbFRly=*={QKrc?lC0$uFQQF+9xG~&On4M`JYcqZiim45;v#m0RDJbn9cMv& z-4<~&bC)N(-&7<$YS=W-BCjRrl9ISD-dnv;(O$tD#r#wcRBz<3DLWl8;J9O@7;np6 zBPHfW*XD^)Sh*$Uu0Ym1;pdPFx>y2l@EvS`nth3j(jDKopSOe^hvGDam+h0y-Svm& zm|lkjnb&+2=97m3iHEb#uMKD4AW!Z+HCx$qiF&E`oE3&+{%&<|8N$QxhqE>}__t z?kh0dj*L;>nJI(v=vuFWEz=s3bD!PRQ#{Jd=w6W&ArT1$9k*%#!Ji*gFLUPw7)8j{ zxkZ`r-sxcf?_UYv9i&HEL3`BwTg<;3{p&;fCD69VVauY<&}Wl@;xq1rWzzkwjv=#uAmP#%LW(?~HHsHvL}*jBCw`Ys*Sq ztHTmyX3|rlKjI z{-Xm8USre@(a|bpEGtZ1{CA^&eQ?0Fy)V5dW+UzFX~X;izjJ-QSR-sF!ssQL@Cp1E zqIf~_k@9AyH?K$^LPq`McQ{^S7K@`*a$Hwx-osmcLZT>K+o;e{z9&ujVhe!`_?_pH z9EnG6r?nmaWD&rhsTvdJF}eg#0`2uVUE#mv4h$lL>S&dsYNlUt;jO-E+EZNHj-OS* z9f+O~3w`{~RbL*7hp`ds`>Xhq#jVfqS;+e3L{t&jcoe46aejk}E`}r0=gI>Ej%SS$QI-@cVuucC<<| zJE^uXywxXwYvbB#*Do_@V~m--)PCvQ=nwJuy@`)z_4g+J?;Z1d6aRIS|K7xZoeiL- zexJmD)z!aGV!UJg_euPhWB&I^jBmFbnbRkG5KJNOK`7MPy_o}gW8Cyt3zyqu41mB% zI2RUolh-M2_PpHOYPqtE^E+QrmH4~({XP+lHO1ZnMjE(XQT~{V8Bb{i5Wu%7_CP#2 zX)A%XENg!IiEAqFfDWa5F@ z%542R8^_AjHi~J5XXqwT&qAN6&pCK@FWi&rPH*+e4g}L|%xUAjJ%Feufor%<{=L;^ zuaxk6w&o-P)%fQ5Vc??qrV}PEE58z%IU|F;3Pl(M5*$^PkI(=$vB7j zG8Rp|H!~mr=DNTgK{DAv-Vh%AY2Q0bCzH6@2ZHoTxLPW^YamsU6I)sOJz?0ygtxqSahGk!jkO3z&%!kkbmV`g4!&^= zR1wE?UhYF$rdVbyx|G~y+r^>}cZJHChLlUHI~6yZ-4>QLhLp-`hA2c#(=MVN4Wi7R z4trY<>^}y}tYo1#FXD4i!V78{V=|=@7YI( z_jtxUs*~g)5T5~r44-#-K&e@OqVwwljO^dYcNb|^V9%0L*3|pihxdmQdlfuh&&u}2 zQ!VrsbytgFKa%0E#uz(XL+1Uv5gCi}TwhV(IupI7G|im9r__fx1~4xsyb?^MSNcp& zG#X#oD7dG}e952*Bu}_@>~H(RI}k}I-W#Z5dRdE| zTmRYP9!%|so|jgxzf3Xy0v^q5uRt2aG0IfV{+~TwNeS?kuj2B5+ZUedA|!HTYzOrk z-Y1>=XOCNu0!U$!Ir%>u>3?YlmjOe$W!wAxSLKf{GPoIq7Z3q2dX-A|?|%H{Z&0jY zDEX3r;qi|iS2ZC7=+8FkS$zHWS5xobJy}PAq4d7;bpI8J`ep5L26G;et%AM4U*!0g z>Bh-Nkv15L=XC=x_yXflFinjkp~Dv~iFl9fz1IZH+a6eZK- zpdhJ9lBG$r58V4*#Ho4j)IU=-|I|wra_kd&@4eEqp0)M~x}%~%Oh`+JgM&kS>!$2o z92^2o92{I){FC65I)=weI5?-JEN|SnbL++praKSp%q(q8ad2)1MQWXbtAD0S(0%bt z<~jir)5XAXNh zNNXhJVa`_bM(ajP)!xq3SKrn+@zT>cn5Or}4!p=?G6@+nXX(z?-c-3|`YZt#ul*q> z&9P}cgX%Yw^z_Hx5-050F6P{@v(P$!UuSP_FE{No^^X-CnIvYFsi~D^CMg^ogBJ4J zgg8viZYvxojL!uSTiiDCC*^zgUFk&5>+en{Mp!q3B1~@#oqQNf8^!e*@1YC9a_Dt~ zOWkkRuFYK-Ba*|(5M)|!`4ao_=@nvQx@pz`cv_p%-Zi!ryO^09F?zO>q?%vlY&rct zcscO84(w@%?;+gZch=Ep=4G1Rx^80X7~otHEy$r4fM!~tOjVG-mUUw36tm&N83D!5 zF9I&HZ>!xfkfQ53J$-%duYXQA$A5H{w4Tymg_6pCjJfBLn;(-j zyUI+V+GP&Sb3}+w&+@btce%A#BDg}F4P#!`-o@0kp0$64rO9UJk|HoB{7CiW!^fL} zmZaj7Qy-sjdCOCq=ChvizR(HR-lZaKB9vu5M(CZzf8*?V)GFVXFN|?~B?7lU1!;_V zpU_@<7mPJRNaRTPUZI|QA@fm@rkm^so5JbVCw%y)?|!BCyhM8OBZsq8AQ7%HrHMoE z6;Yj;h**LLH||%S`16^cOYcaroRaXna^~?PJvW}nh_l3UxA7vFS+^COcx@!!*zwvF?E1EyDHuIR zb)V%`s1rZS4e$1sG_t2J1e|>oR8n?qA;fc>?C12ESi#nhlBcGYh7*52ZolPrvrK-P zWhjQ7`}Ov#37Ym3YmXv}Z|>z&l~Hy()gQNK%pi$$&>zCN@-2s-glOZ@^I@hhnv*;z z!g03wnwD=*E8eZLia%Fd<}Z-$pPYIwBpx&PEI6x2x<}!;HTF(b{|!m$CiA^J-ck}z z_vV6lYS&H7^T_+I&hhu))AR{s5m+~cfBM;u@!&Spf7D?-vH3%W{=4)T@rbte#g%wW zoJU+WJC+bn-E`5SHsM0TB{DNJN`Cmy5GEsgS&1gH)8=gE)HwG?sT*czl|#2H{H9BM zrzUrfJ#5SO^Ygng`aaJDXKw9bgzt)LYXE^XJrXAlF?s9a6GD>A-4oWeH$Sv}mehv$rV*-uOuali?B{E3YO`$$~;yx)?Y zKgm{WX@5))x3`wQ%%i-HsQuK4UmL#vGg8j$3aez~AJ671#F1SZ3&CS1yUG2+KZQ9u z5dS%g;4}A|SMT~|$%!x*e=X>u;a4@nT|iNyjHUCv`W!2Nk0Rb+;{rZL`96p-*BddL>rUPkeisO!8u?1-OAI3 zpVJIN8?C{KD%-U3c(bUt0?8f3T5IXQ5t1~J+cQX=OMJrjp?7R>>0~8wjlXp5)=xV; z&bnttsy|um@jpLS`ap4=Zr7G4(X z7T0&nOLmU!`AzHv&lhJnfhEvXPA~`Q{wsO{SW^%Gb8b>Nd z(sL@ncu^9tO{E?t-4|7#)b2~U)4CJ56TN@p^?XQqSE(ZfuI|OY^vb4Luh~jba)M%l zcOndlL`EaitwND^oWn6zXi20wj4{JUqw8*=x(O;w{Uwq|b1=9JaBS!j+$QR zs><22eAB_-!(W&8q#pBBpJCm=t}LM@K_*wpu5?7WN)>y0hiT{hjwv<_yK&n7xcDQQ zM;s?-iB-<6lJqhxNXCg)+We~iUP`QXL%bedKNAp3JV?A178-Uv^rO6Ws0!^G?JVsU zojF}Dzm(OG$#u~sVX~Mk{;OuoaqsGl1Rk72okN65so&_jqnL}s~z#~J)Xkv z2#g^UJ>PvEPV$7rndHoQXL{E2A@p?ghT%mt(P9t!KMAtdTz!9aLJZ+hE~sd&(U&o% z#*=IyK6rH{4i%SMen;P5->gFDedU8?{&I)tPSzsHwp1t~Kr zy+max{p!=BLZe~T`aWqsdNs5)Pj@GGz4o$qRkcg9YrNlTy2FgM*Gc=!F?m+N-+p;shSc+&a4vf7xz zb<1?z^nMNed`jj*_9F1L!1S9ufiF!%VMU=7aw776>?+;M8J-Ke{4~3Mhr>(zQ%~>g0Vr)pP zZ4pbhSKU4>wU^YVJw=62pVxly>Os+u>Dv4xlbxo9CQsG-32xnD`D?A8f4tNhG#(IB zd6FpRDfVmivtX8BQ!6%3(yMh=Z^eCbvyo_lns#7#;LPsA`c@suMtDF719dE~yMfir z`C<3fg3$?bE!^C=>gM+z-*tWzx6Tsu+Kte-CeL2ln=I6QUurPSTe-8@8dveS!gNDu z0X8C9X}I!qp0T20s3Kef->ZF>f8l$)LZt#9!<6)Hr~dL|Y|3)x=dJ)kWy{*sZ%4euC%sT571B;3TnA;Q$@ z9+Mlw#@12HO_F8*3NdgDeay$gw10_{wImB%`3}vr%zNfrwyCwnnIK37*)UROb0y9efc0#~nI<>SB1clk08xPr&g-PY-z8;`9c z>%l|*evYiEqsaqHdnZdfTPEna_l)hFog`UUpfCELpM!Clx>^47O}37IO$$tr4?4pq zz{}6~KhFlYNgcU7N7Dy4>=58PouvMe*IzduKKa*;5`56q4=u&PI`4l97Fvo>g71HXCPnyaN{9u> z@w}z1ss{KAv<&(=MhyO8KllqBzrX62lwyp7BZG5G_L_#MR(a=5}iGJ zHk|Z>Hz8L+ML81@5knp)3ol_-#y5|*D0afE(r+Hw?Ck7r4?}{3r-SivISud`@EP9b zvV8J>Lihf|bD3}Rh8KrdSDo6NT-UxjIeTOF66edeGTXW)5k5QF>1j53bthFXkRQXv z!zX2ud5H5L4!ZHu@HNrgU;oXu;2I`!(yZlc|KhpO^JE@9G=d!ul>3)M!Pne8{V#{{ z_L@u{^4Ld~|1i0~pN5C>I{B|wgOsVAi3yIzF@FA^*6puH`@^J;|GR}IwIC(Uvck!~ z`5#4c@aQ_u#D6(Ed?9>%P2q>|3;$W#(4!w3MYjFR+2PUR;h|_{xX=DOfy?AIoBzw% z;S%He!-$!v2>uq)|Fw9S;1h!XZgx0+Cy&)3Pm+fGOQ`^LKKJit_kUNNl|1q=L2L=_ zM1PKioQdDG`4xd1wVfK}oeiX-+r^`k3(c){Lswn82v5xrs%E4zXZz!Vi~I%+Y560r z?WHJBVvjQwQb(-p?dS;)?TwgrBbfI+%Yhq_j zzZCRh8eFlX?&$GK66%b-MMLM@?;@|8ncpr5SMOwjf2vzm{!s~;{1c6Z3&Qv6kX8;H z*EIyqTfgoG5A*1#{&UH}SFxwncBbA|-mBJY=zYArIOpvRq4$e)bQOc*)fsQr=s35`}C? zHHs0o){Fs<{SoZ$di1+-{O;l2j^b55Be{A95pNF*Gwwd;oU7(;^T+oqmCNv949Kan zV#Hl-W5k>>Dan?HrG2nSwJ&kMMDeL^jQaW_o)|%oi^hUM_GV~^{NWld$-Sj^&UGNt zL{mo@`-BPiyrH;Yr+8GrO#J1wqr2;+8jKmpM8=&@4{Tu@oaQwZR!64t)(zKv*1#Xu zFzd*3>8M;+HJI%DGSkC2YCq$l2-|PP{NYGHkR7#gMc!wnwHhK)b;yFX zve~2d7tHyrbm1Z#)}7F6dt^ipWg_sFsor>Whkl5Y&qMO-r@lL)Niv^LEcaC5p%izI zJ=i>Q4#%(ZL|Op>p=M-ulRn=O2Y*MyuhN;X4wKx z$+9?=v@F?=j`_jCm|yrl)RQ`LP6iT>jlVz4bk?Ew_7N4JfHBz(-_Ap3Nahazu}BOA zV8Ck`=bl^*GlJbKSG;j_%rA)c#~itR{KxWAZ7v%s&psd~pxwz1NX*4`oJh)%)>IpqhKe zbAI#FU`^SPG9%?tMldx`gNi>EN%AZhFh)&~(2=$d`N1hN;OLkyQXh3K!NvEGf1CEGMd((xlNtuQcdUZtO*xw(F`LnbP zZ{m@2O#3E#?Y}1bUz7dYJFfoMWDoh1|5cNv_3&Ar>$j|0>$x35#iKZzRjA_ev+h*a zTCZVZPQ^mGP4&GEHR^QL#Dsu=0Quqc@}&+1M&$_UT{q|a?A|M`l?u-Lz;Jou3n~Or zr4lbDtQ;$nU1BFXpTRI>H=kMZh3n98A;-aA4je+)v^isC_Rje%E6oT@npt;NZ&Cn7 zaSE0LqphZTIZ{=IC(p}!A^5NlyCZuLcOt8*>q*2@w5pdQEvMpLZO;Xiue6GHxlhGM zNv%Y;rED!!*nMsLV&}UxDC9W#RbV58{xy&8YuoD0NvH8J(KI^SGG=|RrG}ZPn(c{< zCWZ%}m}iP}y%C7SzP-1PNRT|Gf-9SCzEbl=T`I-;HEY>+sS#d3Sc@lA%&^&#@kPVc zzq`M;U-!dL;p~(Vtk9$TjPI}d)o|BJR#(yZ2hALogNRakmxP88>hxjPQSUx6q6yMF zMBEC}6^e%)JB2=oGpN-%O5^-0b8lmB z*Klykres`>TK`qJ6n5GP4bu`Hj2qc(bxqsZ7_BLp7p>V;76TyD`pf)RucZ(}B`^kk zM6Y0*gdnJ&FXr;NUhcA+pGlctKY}PssrEyfzVsFS3%-@a|+a~(#RwM-BMixh(wul4AfC#z;xtq6_q6}^ zRe#S$hY*09Vu_`Pw(Q1vm_|A~CC`QT=14owis8a$PE-oeU%u>;0V`G#vMkzbcVj56 z{8DGEs1Jh?zv~eGi4=i5e;{B>p?4i}fKN5qPd}x1=?lbBpA#}^40WnKb}9wPz6DDD zipLq;zWEikNo}R*+Eo>o8b(XUb|xX`$_J6d>O9FFi$Ai%+Cnr9UuxqefD!Tm>G zYeYxN2)3s*P1p9lX&<)niD>0_;u#)0_b++q^mrE??9Zpt5;pqWLR1Bfgqko_esAom z)AmwR1ilZw<5z*1A1_sN7G7hs-8z8pxfXpiF_Z_W%!qdF$MLfKj5;KZv!uM?qLbLf zEA`HjLEFJq{yJnDcPc!S3Lb3h^8B!wvsXf@#PJB0p5S3MU>1w8if3%di>mx_ac00e zH#^%}m^|WS=y>Uf$Ls*F=#c#lkyjpwhURG7M=*z9{wIh!&zZ+PpZprFE;SLcW~P4@aUM@4Iv-2<19Qr8k2Mql~kQSXj_pwz37t8Q#y3nduwpi_PwWQ z9dap4UzUdrW3@5tYUnZj?x{{mg-<;Om79>1M$xDUBCVr@}jyL=NM_w?+_LO(oLI27ZBKp%sm0Ln1rlM$Zn?M996I*8`V*mkc50y)J$}nm)U^##&B27_LrKJ z;$8#s23A^={Sc-sI{Yf9Y%JKR^A?-wl&y2P*=*uU+*FFbOaDd5c}vyXv3Aw&w6wI% z!A8EDUkvYV%Ng+zx+ySvI|ch2C_%}zo#)`7JP$_h8lp{d@`>j?=kjO1816n89A2s3sN$=dGv%{> z?<-!1G(hu?HGazI*GQ+4+ijBGbr=9atjjTRYp4jVshi4E(#O*BMu2tjqSaLps`$Df z+lE|CwFjI^#iJv{;MEw}Q{N3&-zc-zxM+lKiH)}A)+VsR7^#i-ZO$6EgB&Y=KH>Y? z`X1Q#ebL>9TZ}%xzEezv)L7KNpGwfRRw#_lSo&z_jQyBdOf*qh}93I-U_h_GC;x7gf0Y%WD&RYzLIVzv0- z;zx4TEXq~mJ#&fib3CK0QfD0W$#Ccp!PkxP)*3lS!dyrO56?ly$R2WfC$-WxBPluH z&byma>E_Z~{l!E6C44oc$8MP*m{J}9A| zm&uDSouJlx7Jg+c&Tw8YAV)&rm&=zfvthwYLSW#Ti`o0;<+$S9gbUsPL5bv zxs1A3~~!ia33LLaj+%*eel% z8%i#85@oDUk!(zn{N_@*+w-a!_C0f!!Ig-;UlIKoY7R{%73xFGG*3!Uxz!#YnduNk zYS_-GY9TY3%%$2~?|JKfeD$zd)R#iD7R9FXj!FX#P4p;~m=A(7E11RNajKZWFKlm3 zg4FI(gzM1BQ-6ooeOc8S5rH5}T+;dpg*tPw!Am*W$8E^S?5*DUB zW%4*9LsBEXtb^N@VQV#AT3=t-Di7IP9MWh6%O*p#dI8xf^LfwQE_|LnAaS8;Da`J? z+6qc~oif)=PBS@#ZgwEv_*HJ1_D|QEt>M5Mw6oT%E*ZLHAezL_J|t*2*XNgBJXrY~vr(8M*e*<4K4p0iMNS!6N`Qv3*SK{uf zPK4_U<96|*rZ=DIvaq$Mq@GcFBJIeNNp@DG_Z*$`i|UZH2?y9}fo+{f~thfwpW09<@)@8_AlXFKRc z@`kQQBx3A4z>txK`mqsXx;A!k3?Mq#yehf^VFG1`Qx>R9?L5x#pzr;3AuhcJo(Pd5 zug9N^r?=eZjK)_P_m&uEI&bqK^bpa9!#kcL_kR9f&T;}}ER?M3v;4CDgRB5XV~2ev z8_Q?gj?Crx=s?yN6x)SVM=2Z&SC}_0GJ=J6J8e!xrI!Ug=tz=-aPTelG^I?D!kJmg zjiHyjATXqFE!IeTavK!AUpiTmQ9K7gi{<9>1ZyjqXs2*MjB)xEyY3TqU;&CYCu7so zrPeZ8tu)R^{FDis5klL0~|2XB=((BhyV!Z`Bhu!=dV~Cy} zyb8H)$uLR*qpCI3c!mOtGCiv!><_kaj@V~J*hBLe~e-&f=L&P z|M1-rm^_Tm`L%KRyuK3^mhSFu)JSV9)BM_K0ch9lZ2%GX-8@eDh3Z}GY!{SF-V@Hp z$96|ZpzVV)1wJ~}6N}zodr8AAVY`4-Y4L}R!zwIn)Qj#F4UDW0+9j%p&7@eVTj!d` zImlxd_jVTt9_%O$eWEH(q3OsFlVhL%D%h6AYnGeqvxZU_ve58%IG z>G(2FK#Hml(-$^=jO`=6hCEJkg{c95q9rZ6bVO_i$_n$89ZZbI%lnw+KL`JW?@$yc z1N@)r1JhlR%RbTAka?;E-QdFVPc^^@7q7djk?|_XnVss8qkFp>^#QBldx7B<^^GPN zA>jEbq4d2!LnF+!tHET(0EC$|{3VU_AWj2~QM;_(AgeZWz!uzlSID^i?bM9^qKDR( zNx5nEIi&iy{RV`2E^lDgSK6edy~pWBGkC+@5Sp(-NcG0s=LK|NJNh9Vt^i7SB2tiK zY&lsLnnPBnHHAr@`+U9_mC{=|DV$lIG3d6?_-<=lz(4WVM>bm5LZw5@s9!aC;Mm>m zQVpf0QQr@+@h&-l8^^nlyOP#BzK=Gx06y+`O>0L{F_RX1Hxy69mj|{4mQXm}b;P~i zA5KOX9E(oasGK53aR?DQJ#bVuK`W^ovo zdG&g6Zfe=F95Fc@9)F89^=|Ug0V~u1(rwOgTNfsM7ls&bj;7ICh|{YlL7ZuoyKA|O>o-5*$IInS2Xp0E43tL;ny0bjYo?b~ z*v)jNq8q{usk!0Lh^q{IjmG1>1u%X4M39h>#vr1o1Bn!uT+39YC&M7mXg092jFWU> zR|2*mFf1w8)l2gZ15(Y~2;I2x_8Vuid14Rek22DP-PBRYdGZ{j;_A9Es2h}K&+HYV zPq||y!Q#IP;j6wP>{(=pBFm;@d|6`CUoh962*k44W>U413MRo$a{hRn|RDikhc zSd;A|CEq;Yxmab5GA=@5CmOLjCO?rbM)gW2RowFR1J1qrU4UiM9~6{tDgWkA6mViv zYCS(9Rb5rGxI~prFbqMTJ8*xzSlNk(U#a`J_~!k-Llp!+7hqHaYM2%&D4RQ@>HVvo zQ3Xo6?L3mda|0$MpasDrPj(?d$WA2mmnFlKo-~(WkrD`X$J6*RubsE2^ur0fb3iqvg;_{IAiB3t;4+8YKTnX*xh2p2N*19 zq-qkBka8|ITv31S53}=GiS6R^SqeG5{z_ft7RZMY#8+*{LSi>*)A1n&N2D0NR+mIW zDPgOTr2=LLa$_g*tYD8%Qd@KC2wTnEpp{UO2K>9ZZVg;k6|z+`0MM%Vpc@jZ zCy6z8ey~Y@4i*Arfqs{Zvc^)9T@1AOH|&{9^?}k(^nx;G7GkUBl?7Uww9F4b%6w+xD^$i%x0z+2fR1v~4;@dW9ZF z>5_K7hZJcUKf`mPV|JnMAX%*jekMH~umr;Mi(XUW^$P_k#B`mK36QUvm2g4(i;K5A zTSQ0Wc6babuMnLq_9)UXwj_sDW>k;DbIJP?-aAg2-N;%5A;?6SYv=nJ-G%{)%R=$3^G^s|*M zC8gx6RxWYBNrFbz&jmaH;?)o$G^K-hr}mn*wZuyodRaq8CBnyq@26) zV`}aIdr+f7`jgi%3h%427?gVGU0A%q8d58@v}R`>-Ox<~)@DGi1`jo|nkJh13#HO) z=<6Nat|PAA9S`N%_tw&}3YSHCdc_EU>pU^8_6VKnBa6gmlN)Wym_u_|-7`;cH*?M( z@7>pNPTHPX9iupPNq!2YLmH%%^02&D)=GNQ;D9os2fl)1Ar7VDzW5cHklt@?l83B* zhPK&L=~ceJloVg0Ebp1HH8f?`P=yayju&(8Hj}@@L+Be8F%A%>j@WviNg?wfohs>* zPJFqBI}1zHt`BkmWmX?hA7KJqZkVe%uWkwVPM7qK`uL0jcLZgY2hfT{5~*L`$eNrB z#~=pD1HiY6tK9;J#z{&;?WY3P_ar{h^kvAiOn7dL(d%~`!ETE7*p128WSD#umTMWW zTxq2f33l!7tOluKx0q#?5!$VX7b^^R22^nxjWaSHq)r%wou@9gzs=`0{Yam5JRS;A zfiL6PaBrY9u~%x{@a{_x7Kq7ZW55+I!LgDR@w9_t37}_&&Qpyj)G_mvrd-vbVlBTK zF6iL6D7ox?kTY6UCeH=X+1>=C^3=_KfgV|A^GKLx<~${#WW~(kF!$JDa<2}i9~Cc+26x< zMED5V+}=s1qMNk_D?OG1F$tQisOoEL4iCvjkiOhTc+(_Te>}t3>Q{-B6tfrCmciF* zbIOOV9g@Ej$J+(;MZE};FMy%e&*QwV;gGJmLvbw@BCys_^6_?>55>j;Svw&b;9gUh zYaT{8*Iij`wf%+YIaUqf*Z~4ffL-Kg<_g;wT-=6E z(Cj^;N6>NslxrZjg;K{$X1Ph_dM@TrBw+%LB@zv(7-1ryz2%<3J75;{Lp(K}KZ3nu zD1L%{UhKR4GBE|z(YWJ1Fq!r8GvP6}c9JK?`VKAYwCa+3ABYSC$hPfq>0J|SvsU%l zSH+fqJXQrHLhEa~dd2vYC>DGzUvdMmwjEQkHU+olB}bRST~o^5@waJoANbmY1Xu1u znQ}bvwa!VxQdjZ;QeLHJTqc_jYT7|Z$gfQ&N2CFSu`EVw-ljHiySKxv4bSdK^?B;z4-@#|F+@hgoQqj~U0Qi@2e1pd zydvK8T=3$_80(&ZfZPNod5#cqT;)T`LCT&a!v~zhEERCRPP8_y~S>QYC*v-c4DmH`GxmBHjXV18?L$xJ+XEdz7 z2hC^me&Y4a;OMT)4zl|fdu<=h_bmKeSULov=?GBeLvzJTWd8YWf(c8Z6vqlMtAIei z3=tXSZzz{XwkJh#krs!84Cjco}t~$Pk z-Ya$f+B@2gE?bo4D^-sO-WzUUhdHdkQ8UY5_*D5k`@hKBFaV=E6$;WRLw}e<7`2{# z9e)izOs>qT$P#$e&+UP$4JtC{Y0K`*q?X=klhOH0^0OaUG5gPq}! z*F>raEO$93ti(}VE3{2tvTXxTjg#8yZzHiDK^g8~oIrkhT34%v)K#yCx`ZW^(siPt zI}3-RA-ypVw&n%3X9j%n9q3BX)Q_x^=U+^VwWTfL4QP)jL93oRZ!d!#XWWC=AVnCN zv&tUX4?Fi}XNN=s=5$Dn_F4{h21L2Rz~@<*(k64s;D|Qg-Ic-*+T;3>Yg;kD^{4qQ zL)~7H%30HO$mv{AClYE%9@0^UQt`q8wefXemVkqpPB(&e8-wy{FY$O#?ABOgxn`HO z;nslDC+4T82Z!KKF>-mx{_&Huqeby*=-CZMM70I*4d+kcS{1l zJ}F4OFaTKS%$DrOK$x9JS8OLpn?!BAxj)jI3T(TFdQn6qgA}Z@AC&96K%rGlALbb! z2a<{tJrKeFmj6YR**j2n-$ZiSzP}} z|5h4=qkt11KI}^Gj!SorHH0V#xdK)bs#B^EQS)XYDposh7w(|AXcb-uKh(xcqE%Sf zFE2k=V2B14VHD&DXrt) zZ9cL!vSF6&CtNN!&55hLHc~q5qATLzRprR%4_jh@IGQex+3eoFPzvYVDNvx|V7S&7 zk{JjjX1i8vuv+bSn9hGovtLpq)@;a-AyWye)!3n6m6DUWBu`lmB4&X?o*bDm_<}DB zX2?;|U<Cm5=xRLNTJbT_o1J)eCi-%8F+j-CG_A3XmifCvSf&6v6G1;XqRm8CDVSg9R|!3y*ned4EoE&bZtf9 z!VJYBK17-gpY8})Z7)^-4$CX8<(H!L>Zw$-8l}JcNW=HL=%}jA|pz@ z1ElZs7{97*yerg)7X_;eb@6lqr#1jln-#aMzwngWRHWNMy+>aKnuO?kDt0fBgKE}B zoV2gc`kN0?)vKu-gj(||0zbAO1f5d$C?~4Rt&~mPD41V8R1v*Ek*r-ckFbMEIp-X1 z#<5|Y7KYxlmY{RpK-)tX)CEkCR=2&?w8T+_oolaxIIYTR^B(bSs( ztCyw{AL9cqG-ZBi#n{Ncpk`+w4CUVAp86HjrA9C`JH|o4%6+zwlT;Vq03P)@L|vw4*sXbRLfU00nb(_$JH`4Bz57tccb|-xf>RFD z$|c}8&jE%G>ZC%@DtWASD1bC%_?4tBZ}8cCi5{rq#5}?SwXo4sS}h#!ySs^QaBv^C zLS+{`M5`xayI-^NH$0sL1zT;gjUh+%A_oa5G7=g5^rvuDlc&jqz2*L(C{W%78mfda zsq#3S*A{nAF0hcs-|5|1ls!$AS1>y*{$WEK-N>9H*a`l2F2(JtR z9xw@)pE1@spIgtZ82UXu>tlnE8N#WzNGhDV9H9&4(eoeEXJYvkVr*y5UV z@o!ufDbpQtVB*O5j0=LGGY(V4fd2KV4D36ooVlrh&Vky;y2upHtLZBVoW+J1tR@XS zD2xU@1fX=Bw+gCv^cB6J!^yS z^bJNNk7#VaQYLKAxI$flWWcnuhg=?MAyAz?O#ly#?O`=+e#!n%z&PXt2-~c(rw3?~7XrTQHNr zNB33TO4aQ%tU1nrf1Uw>apsfo^*i^dreeW{2r3Vd?4t$t%C9KEYIJA3=G7N_H|*GW&O8Ob7?uvv<1+BSLnLzSC+X5Xw6K^A^UpbdMlM;VzWj$8A*FR zc>Hhu)%pa0OC->AZdhQ#ohRUi=P`K$_Cr-*Ok0BRXM*Q~rMuB-O2(}o>CT@iFI5x) z9jN!k#O81h04V5Ikpi{E$k7Emk<=ks)-?#7LC(Jlh>MaE8?$Y^ z?&D2uJ<*5DQte>}{oSINaOU;^843BH5cttW6vIkfAEQQ=UzgsG*tM4Mf(pH$2kid( zbR(w3O>Z2k%|gXqEiLyWZHnV8psXy!8-^KwNvOHzFlC`LU=ktOsQ|#15ZGm<#A>C) z2ijvGhEB;m?gSXpxxSg-hVAMuh zCMig$o1$JG8T@F!fRY>`<vLq`PqtoNIzZ&WRMPdti#%%yoI4$sN%)}c7>CxExVm821;BwB{S4>(H6 z836syXy~=Tdb?I+EY`Yj|5(hTBs@` zgJ&Mpt7ZU8WKllcJVKOlYJH^p+~GBOrm%0WoDtO~1fk5NH*#t)uv|quuW`Drx&FeY zKF@|p$JVQCbeR}PZLEF8kF-8jLc!L3w8o-|NRu+V>10I}sQND9*Y0x+pa}JdxZPYU zouSX1KI!VAF#XElz)P$$GUJdl=K*>;9U}kx@5})*;d5YVC4hUKXf4Bd2=PF!KBCX| z#9=psPYRe&U>-|0y3z@{c}Paj)JlXERhCYrn*;V&lXOC>^xpRJ2c_jm)G3t*r`$Xb z2e~YOsenZ;tFiFc;i_ps{E?1hi*Ogj?}Dr#3W9nBwoghA$0o4us!%_tq#+LUyDqOSd&6iHE{w ziWWUNI=Xh91BEHh=K15%ccHr@aWfY{!wH7}>mkbYzz<{L2lqyZYjypxoaD@qS0O{p zrEidCVbVw1sg90L#`-{DJtZZFbCvzYSA_1?AWSI_p~ynk^B<~y9!%iB!v5b;*trBm znk|Xa(#p}7Q`aK<{;)G9ehx_6Uv^I4^6F}YHb`D@2`IfJBSOu#{P(*6j@V`>2wq^* zo-kp~Z;T=oa{Vsv>u+7gE-lbs;jf2#Z1HIpG0ufza@F#X2K5qun6>X;9;4K*IP|DZ@-y#yjLuI| z9^`dMDa>i*KRm|&*3-Vk4KHq_wO-9ldi{IU1FQ6Rj~gU?t$wLvf9}Z(24JK2@d?yq zOKcR_MH4)RjQ_)Pb?!_4q}9X|k&~$Is^)b9`#*Qt9Uz0?&aQ#Oh+$t+G;I42(MoeP zK{F3&S0P{jhkn!_+#cYda|GVu;lEPd-?wS}|FeCY)*t*~D^qQ%pnZ_T-Sz)uC*|J$ zrqfZ%FuM>?!NM4f&(6>NAsSmq@qq>i0~{wLB-B0cEEay$0A!5fpe@3UncCi-1N)jV z>Jk}nR9F62H*5WOf93znTcVZW2bCH1bQK2HKPv*Vv#|6LDT%eH}y*LOEm);+*l05okqXMXb{!+yb`3}fV$axla{+QhG zUzzIE0{b6vs}}N(#HVFrsafFYORt9ixcMb$G=_reXZq>+LkRo8(Y@q>maTt2ae9L~ zE5^cMQQ_$1rd1B&s<^AdQJcj(DZejsrh!V*I;6<%}S?ytcc z8)(@++wRHM)EJ>J@TWr{!6R1l%LtB4LuKa+Jz_bpl{h_OVWI$JGX#z#~Wb=^9 z>=l39d`TOu+P;sSY`J~o#*LR>C;nV~JX%Qdv~8l(U&87*opY}(I`kf0|Np)i;4gdm z?~4HrYvF%i4DdHlgRq@Q3%=jjkFgRIsbfv%=A8Wxm$@`vW7v3(t0~9 z{`W0Z;CcJZ>>*qG?3f*Xgb@dBljhWZ2552DFtI=Yp1OeU9Zq#P>`s9*kqJ7$Xo}n4 z9cGT4!|{Vye$LpW|M)%|S7tm-z;`+|bEKzSy!|=_dg%ZuVj*3g!MR(_5>z~upq|+- zsK%gjJzht3aJy{|C);yBMP|3^*G$y4%Ja#(g=u)SRd3|@nS#e&tN2|wlORGeymCTo`L~F9^ zj;U0SGHOm#SaR!XMcPC}`YPDwbXhmYCd($IhQm@Zc!zTZZNh1d{E}Z)(5^j2;kBq; zXqGBB%c}@l*^J8N9=d!T(E}RF%IwA{y}16_I& zkFSAAM~$FIz`P3&=1r*SJb4k0t_H27TblXli)8Wc%B>rLif|4h@s_L~;bv(<#mnUn zuEJgy+G}KmYz|-*uONM-!choAvN+^idw+v#{>Ef1B7xp{O<2p-!RbAT`(^mror`ei z+wXa+Ls0r;SvvZ8$RPdwcQcV|pzv1}Ya=2zFYLhks}g~POZO%0kOB#tJPR|Tl85vZ zABB~dhOl~T&5X3UMlQ^Ifde3a{nTPZK-A3&o|&YoL)OiK{x3ML59xfCG~3jvj@E%b zRZk+#;!!#7-`e^|UbnB*cfJ=olgr>waFPmRL;WRZqXDgw>w&PC~w-_tm_4Ac=$ z8TcaEdQk{nvTz+TFP(F*noDwD%twXM!rD7xOZvP*PX9upaxtgNAA7cilcA`xqZmTT zP@EB$g~NFFt2W7__dg=d6hT+FKdeO~o3)+wn6&2PqkV;iB-jc`u;Dp$s0vN54tZ!! zp3=~4f%QW2b&c%t0clTmo5UMkJk-fTLw&Rn!LMsYg}XMJKzQjKEs*eBix0$Q1Usz5 zB;6ZRJ*=+Xj<)WJFQOH+558ytl@QbIuLr@7z|0yPM1JMbx4O za~}+q3`$A1=zIH=&nbquv{lw2BSRr$WLAa@kqnvT z-CsS!{d=D7e((Cf>%Z2$EKazW@7bTduj|^^-k?YNk?aV~r{1`fE*Uy3Kiy zlOLpHExmd4go?gyxp8#rvUTOcy7HjU%gO@I==j73sOW@y4e!xW@r-%Brktj|7;5p% zCwi=(pEcTtf25L=E&2A&7x(!Ym2BNv>_>GHl=pkZOD>fx8#))oauL5*+(?Y0NP1h) zzO$!u=ftV_hb``%C}?^$jpD^bcBQ_!mPdt=1u$zQEm4rQSbucA0QNOg$^>SP0J8cGb8{ zj@+szZ!(&SH;}PW1FWjupvPRr6gW4J^T^-TEw`yShc)X$qR+)^vbr%8-cbq((*uN3 zgM2%k=RK$Gm%~*_&oW1o8O>-1SO&sz-{1Jp=3L+anIEB9brK%g)+QvIWF*<#Rbm$fPY=G$ z*M=(IM!&I15ON@nH!|RJ#VpWQ(n_%mgz#2fpWFyNG-aoS`z(e1^Ixe*=Krr$M1^td zPW_*mRlnP;>yi3tyJ_6Ljt}VWobuenkgMn~*K%Ks5U*y?t6Z|FUpg>V`ZW(9QM)vG z%)5`77voqkf7Djrx)xQ9Bg*X)vFN&8#QM~`fC2xFZ6n~p97A* ze;Z2gU&`gR1GmviqFT!GzcTw`=+;SLN4q_YMRyK34 z_#s%0qolyAnByE9Z=)#>5OKRNOFrD$etFk6Rz8nnQ!ifY1A+_?kZ=ac695B{lu?aa zo(;LWClkFtC*f+Y;hJHgy1~+i9~}l9xyiAE#bU-kUo>?neUy95ox3Ufa*VjFWzZq( ztNZTbJe-FA9aKOjS%)(qDh&Uh3P>r%;j)w>dg5X?bHp5rG*SMESN)+I*Hw6)?-;!2 z#)%a8*dNn{yKbdSu{_s=?T-hDsM|Kr+9|%YCZ_IJ&YvFg?%?vE!bIj`JJ!GEq+Zp% zjg}Oyl%jndQRLrSEN9*H+=|@4Vj<7^Iosm;=uMVXNT78SO=6|;n`Lev62D|VyeKV@ z3mR?zjIMH?(lQbkw`}skMh7q3aU+RlwOKQ`g%)uzRbg-B*k=_h!7&2Ut#S z-!tfe-F?5b4zh3Q6|4ocq?iY14$}%D0Yv#f@z%A^L1=8Brc90VbdvggJ9qMI34JMc z^tHXS-%jXt9B_ub0*?{FsmS7`FPd{ArF z)wa~tSy*ED)b{2}!lq+N$g`a8-g6T@XH?7*Qed^u+4 zA&C5ceh9&k6rUWhwHqh;b@E;)>Wj6VM$vXK*{WY-?aQc;94urc;ABQ%9RehT!#Nay zCdtZ|4ImwsM;zw%GC>vi;d4Qu7e*;k`c0uPFB zqN1lta!-{{nhL&QR}tBOx$WsmUu1A;i-c+W(Eir963ybH)mjE-5~ z)w=p`Ey)WQZnn7}z3i@Mzqta`*LecxM@zs9rKtre5g;$>LC|=PH~HYPu+MN zD`A{zc%T=b6DyJBQyHssR##H@tSOX?k>Q+ZT8#L)Uudt<&e|jpSv-!I3vFRpl#>_k z%v`xB7qZ_HmVR96oQ)J5Z5kpra3@L(d5+d=_TCtnUxgJ9XOJBcn#Ee(>HrrWt{@7- ze-XCn^JVe0y63|IMpJ0bp2M@k8GDcq@ ze3%GUW~aB`EC|9XS1H9dQ`xeoIfhqN!g=T|yz&ANhrH;hiF3Ln@Ci1KNqIQITA>_r{I|S_>nGjwQ5Va{ z@>ZVrw;Ci}e)j?mGSHTYeQ5^hWBPptz=aGiXnHIdX9{Ta3;OEXYW`Cn%dCuLShUyq zW+Oa`Oa~vXfQ6@;uz-u*ea)Pa7uzs7QjESm*H!gOM2LX%7pYlO;iwx84$*RvT;P{m zd*`}7^?cv3S(rQ}S(jOtYL$;~=}bYB^yz}6va>fgW;^>}5@~qz%ZO_O*VYx&*^fh^ zt-2Td^4ZJo?mw<~#<6NkwA0vQAO+TQ)inCwl}kzSw79jLfXdU-i5+#T^RafFYKTK$ zjl;NmTh(ojV%HihN(w4Zr523e6>OmUqV@rXDcBQ4gf$Z@v=gMgM`zq@y4(awrD5m`oybdS z^E}x+Ta&6U-p@}~A$wzrghgB`kxghthX*L-R;w#fr2uHrc`u8HqOr45;{8q0*!Mbp zhJfdnlMH6Z8yYdEEb~|i>bBkWFFI=~KIZKa9@amUmuQAwdMnF16#sL%sfAlp#$9W_ z{k~!J!jHH=sD+o8VfmJhUoC^`Q)IK{8|l;BQ!9gWev;l#O@p)h;=7GK1`CnhyO1!X zWMRdirjnADA1h2_R>dPb*`AL#3Cg`nq;frWi4IfobrDp?yH0ic((!0N`ik~_>5c)8 z6+9Mg{G$VrR%rZttnyK(0o?tTfRPPZv^TVGWO|y5zHfg zBT@?XfBhM&TVvqsceiVm93Rs0L7!Ie5H7N#P@m(PIWAii!-M}yL-c(CfN8zi^?ec6 z3_Z@^@vNInbVNHK5n$EoWQXf}aTS8yi6V=paI>x&_58*Rk_Mn5m8yjqOJip%Rb^~N zx(7UcquIXt-YfO3%OHu=>mqFLn6VSG4dOJ+U`-NXF#9Hq?mlO$!1?WX&XF;_ob?uu z$}1ebIKR~OHP2ep0n!7VXNK2WTwxr)+xg;;YCP;;5%-<3w5O1e>G za(sfArrW9zJ+4h(Zqi?2a_-zYsh15x4K<|4JzJ}VR25{Y(*0TJwY}*03dyMs1t*Yw zuBsG|f7fDFtS=}U-(0>SbI3dIM~>_Ze{Zdpuj@l=v5gnwgp6%wdWgvM>FOSg5#1LU zoyACT)hkPpvf;_RNvsqLov3+o+3&tjk)IoKtH%|c#PmKqTq4FSXS!)5?vY8I`-m?R zbM%>DD)rY_CoQ@-_kTGqVZ}AC(|M!x?a`T!;+VQxK5YjJ%5V*Ox$`6ZB8F_)wQ)Tb zOo`u(Lt3+6kuhm&^`t_Km-=bkCy zvlfFe+Se#^(p#cb74dqDoyleeXKz|9E59I4!@%K-%@K~_-UkmD^-JtPQq%Ox*!b~P z)gNX)d^L`rT^oD2^o~DOY|8$VRgBha8$w@EzcEG8+vgU(caj&Suk=6cQy-;`KzApV z%c_NXoj<+3d{lWKkMwcDbg5{nj8LW;U9{jA+TiMNL5t*1JVastF%jK*MwWtCnwv*U zf)5EB>J?j=JAPteO^!qp(>pv4*VXc0cEIbHCruxW)FD!H)%kgc+ja>>knG;hd962| zA`*fArtk9fqaM04FDZ>TsaHYuwCE`nc~v&sp1EQhE^~idg{k+`kI%IZ28N@rUU!?Q zFe9AG2$wiP216Rz$2(j2Z%t=EpM)tX2iHndzqLCL9z1wUNJnRw-3__R?G>sL#VL?+ z^kR})`5yCE4r-X`LFyxdU2BK*vs?DQQ+IQhVT6x<+V%uS!HTg>Rc^j8YZ7$v*jQ;e znsRUWn2FM^mx(vKXY!tK%{e^jOE8f9%)qiMC*9-B6ZD5Q1$@>Ex zpDK0AJH1!0&h)EZ%7sme3Yg>ixWZSNR?c>jJ%-$; z9#^ca_+h-`5d(G2__=u$`Q|WX`BVM~bW7X%(iCq{H$i`tlXIM5(`bINu9Zd3RJ$no z^wDNamyTcrrrh;VSSFR$hwzt7GTR3)=+=0;-L9?7dOGgNA>m5(W2!%HzmS0KC6`)*v@iWZ(qq<}7RaHzu^;;<4sTX^6$iVw>Q^?66hTy97PGecBI9aBwB%}dVL@t7RtQ>C#{ zJp0N=R4)y)T^u@0wHkqTuF)I+5;8vF9f3A1hR;KEhby@)yQaHNVx;Crw!e){+>1nS z`k24qe@)#U5#ee(c1*DU8c&3YMaCsXMSIloU}EEx%cpR(td}cmi5MF`NzX;jfA8Aj z+f*g^BJ8gLuB6(tI6sH2N9hn28V*PQ3huga6)rN#VIR@0*6qz`nL5~-paBBDaYm;v zti>FWd$y2WUY^tfyD(L@oY>)Rxk>mA-aLFM{o~Y#+ObGb-x<9smK5B- zaWexAV36L)`OJ|yRgc>ON1RVZnAEN&EuQty;4)Mq<2vL1R3T{h`D6*p`aP!nS`mvf zjrrzpLL>DBb#tG>uKeTB5>{Mz@Rl$ep3s}F8Y6!!0!<_mmo^t$JCT9r zCJ%i*y<>5^9C9z`!HNW(r+3T`l8_<)(I=C;^9W|@vzXqyz4H0RripaSnS02labW9oWPT)SmyS% z`x80byTmVXc7gSKexUpnhVSh7`ieX1Oiqv8za?qS2G6^EeVL<2(?*eB>AT*T)n%VP zdQV&EzFx@N;4II|y^Wb9bsg?K4%BLvXs_Ma8B~m*U(fE0D>{T}1?qIhE1&BXk5f#3 zmr=9CenRubksWspRgv^}IebPiv2hs-b?{yTsdNp+5hW_uVA7B`LaxEP4pupJGqgr& zK8HQ|$kzK!s415`hG^??lYV};Z~RcPWYNuChmAoT6;Z_&EOM_=8l-2TrPHBS$N%Mg zF>LuvasM{ZJL#s_g(Q~n54TO zU+`X7SP1oh={zjte<7&NMm^wMUjXT@$xqcm3yGc26l@BQydIXGsPf&EjNV>0zp0g` z8qNKo($`zNwEVuhhQ{DNhrpNy%c#!qW&7+?xw!K~zIe?1qhmPb8+AdA8CZjf<};5p zllOkHNzUM-3&FIP8MdLOHz7KEk(@pn<5Wl^ym%lo@f-P-LXjY1<9Za_F_~-jbugkH z$7<@+zQQNvT(z2O7&B%vujV=L!91&uzJp&I?nx+%7o&i3WmpO&q|wPQai)*{mObbeFXGBZ|dgnVVqx?qOGVcL$5E zkwX7VM^QN`1Gt%zOvMs?{`~oXj0|BJIRK0+K4&aM$DSxrX6%y>&>bjtmXoshF^wjT zim1Hqm%F+)G7+9C?66D@dGO8?UL~Ek0#6DGPHmViG5Tv0-M*5qovWLko_yS-T`}7n zc1wi+rv<-+H`##$2WryppFlNW8UCv--i^wi7#(hsCS$>GW_w2c%HtE^7&@NqM}POt0P*Yl6W563C1XmZ64t4Y{Td>Ok`7r0CFa&-Z2 z?AYw)-N!SspH~zaJgESsT={#H0x+s7ucT(C1^e97GK1Owvqcx^c%MMJ_>O+M4*5R} zpLDaXUDxE+9idmB$fQE(^o+(iIjF=a5X_zt8f;@$exKg0m6lrjpK)CcfR1$s&>ex3 zFn>FWDgw!`CT$FW@!+NIa#sYt6o+4r~;8)l;92t_PV+{1}(F*ut`kJd)YzPGEtD~ox1G8@19Pz9!ngvYO>QeMHk1> zE`|6A2RloaD&^kI%eYnF)OYxE7$yJ-TYnD{0*Q^Al_|Hr#4myP_pasKz5VU54CEWF z56EdYZD|S%k2Nt+avp8)szjvmr+6xUTV(xFZrZ&_SG$+$7-Ikwn(M};o`M*b_UfQ4 z`B~*WQ#q|VRNk!*0%sF8`ist-*EuzH82*_BGHvIJ*VNh)uGjBy>JVN_c!eJa0&g$WyP@+Ae-eZ{&M)2pPI+-J2maKZn2g8E-|8+0EEo3Zxt-!W za-=Qf$JcC{dX%9NwF6L&scaIM?dyXG{wprCeLkKlB5bMZcel;!NI#?V2~gK%yC(> z`Q7d+|5c8d%*;%`ocA|Ftunbie#2g3oCwm{&NObXPHS-8f3KEGoDMjNnYCeu;5Vvs z-pHD{`@M}>A}+6sA}9ThmYwd;?MO;)Pm+fZNYjHc)bx)JaT?T-D4DYw)UhZ0H7`p$ z^qiCmY^s16s^_qqO?5Xroo@LD9^ti#L1@|tvCDcD$|Rk3IqVC6!I04AZqgHEXDz!7 zt)coI3=7VpRSTg%qD*&^(>;dXjb!X2oh6os{;pCg(JtsD1`Q{GD>s-tR}WAb7q2Bx z1X_i?WuuLuB_e{MjX{Nd89rb3+4RmN+BxiwK>swWC4MW1>~i!{`%|p|%}Yij$=lH% z97d_ta;3!)T)5)@bHcx)hiEx2l8A%5&HYOJVeK@7?#mlxE^Dh=a$6r9Jui(yYJCHT zMOqG?V=ux2qf`&WN8tyN==s@^I>rDB=0tk@-nUn+)YVbr>nO}@e%Kzu*IFV|;a2hq z*BNOw}J95 z_&O)cu=`g=N&XN;LnFh2f0<^19nHAUiyF&+5+pb~%Ywa;-^(;95TWS6W)K~YUQSaM z)+I~}2x8EkUgpYgu4)~;q7!8qM5Y@R6qSFi4&wYjpF0xb`=OqdeE;>_uj;gSA0a=j zEoojuj;!s?h7IovNiy@Vd^g;^fSA}0mEWQ>nHaez96LTzV!`6CH2UCvb;V)tS6vd@^jWDvv zV{|h>y-H}lQm1wcfoqxn6Rx$Px;I_<9}`+R<7Gjo8P+wq5g@1=@2DEZ`2_Ya>k26# zy&YtvUv+J5?bM^V%+GdTy7cNB_HgwvQ+?pTLnRB!OVbE6qPgA_djiM;iA35q$$=t^ zaT?b4cCL~0q5I!vk`yyLhB>hbikWiIPGBPs z_$j%Cg~eDgDoi1sZFCX$cvZGy```zicBiMBoov=3UI?okxFQ!@y zlT4piwYdHA@{bgC*14zScjWPtgQ5Vv{NSO@AQ*RE&4$I^uaxOR_qC{IZeTrg_Nixm ztymU=gM(ERv}AuU`vN^FNRA_4O2EAe#2fg6gcVtzMoO+j4HWs|EdhC`StC7}Eqdr9 z5yCO2B)_`8m)_d?8i5uxC)}u=)URo zQ8FUpO4;jCXUujW))&aqB>y1ElT_ZA0a~ul&2QOAxy+xMSMB36Z*8bTL&fr`RPN+B_KT`8}WD;9!)XhpB|0JN|Eoz@}rcL zi+Aqa(J?gaH*16bfI!?5z@?Y@OEDo5YA(Asl&~lxqU?+_pH!Bh}z~tdZ~}MIoECg$KL-GBmP^$i%1Aq z>6HnlBbPr|z5_Y#Ws-P&8#rL%EVO4>^JA`Y7?ZApD=1Mdl9RB8Cq@BCyT{(B1*%{C zf=0z);_e|yNnLj7)wzxrIY}fWr)SSAE9mUkZLGekm8P3#k`j*o+Wk)b!g722U=z0D zu`U|TlEYLES=-E##h-iaCKW_|xc3v@qyq%i?&aADjEDYy7Co-qW?Z5Tw z7zlK?NfbOjfAM1M_GhonRTq?iK+JFt?QGd=JVg-61FV-0D9sZ)N;6XO=67P@+#{m8 zXLi9hZ}bCczU*DpW>$7~D7VI@jPR`u+l}Q4kDm_6jePaLy zCxBw^RaEurJ^=mS1nncw`mVoqe!oC2tQDSTRPx|zYsv{NdLAAv zxTcXCmUn&}q-LNXBc%tNOrm#~nY#V8=b=N>DXfg?zxV-A24bTus4xRBM$~|0fI`E- zhLB_=9(Gg55>-=Bj=Bf)<3-Iy*v{Wrf_lZ zw;o~;CbX!}ANFLbSa(K_=JWWGBixGrH|*i?J3Y6{sm#;YT~yuJNTc>(iMXr&bdLTW zwC!Oe!)9!El^~09{wa&j%-LVQ%s2=OnOtEA;;k?fdq&mj2ravuU%3NvBboI;p>5|R zFdXp^a~|?SB$GOasWa7O>5Y>Y+AHX;-5L*9q};30&8nW1YnMPH~X}m`Ar-DIhH#sf2h)@hF);to|BDzXab62#;xWm& z`iKKcj{R_h6Ten-U2W)(n+_5t_ckLXhtfd)3GkefclfM9@=m?NI|!ON|A{RxN1zW( zxTlRN*iIj0Rtf3QL%+xicdx9%M!eIxQ_Lx$l!jh%qWIg>6|GJC-OtO*%gQ9H2Cez{ zWMD4nhr?>QmkOK)rP(DM9y=_u<5vUl1}Ot#6((gR(! z8RV__7!fk*8nrimJkm8O(f-0;L!URm56ZEg?M_~SgC1eWR0Ps=I~YK^Cpo-i6l#ax z8W!2H%nnr~zGB3#JTEOxI4$*->BeT~i)&g^*tnrD0aO@g@n z*x8??q{g63u?S})4D@5}AXJOlr}KB{PC}36;32!#hMuMn*^94uPG7$-;XGtDQ&UMD zXcR*~o=MXCwmM`lV1G~BGu=G)@N-=?Pb1$a$lF(EM|%j!R|Bjfl{j6Xpdds6RbrpU z5}e+{cJw4%?Id?+NnL|aq^Kklc%j)Cd`@C=CttRp%Zi+bE5&R(j*Re;RP-O6cT9zg zQ#xR?*DeVqmvKP}-9a$xyY|^WzojJ*sSj-%e#f5t>W?AG-wy$T7^(o6mCS=EQ3%Xx z;6-W*D|J0CN_XsXVr~nIbeBMU^aTygjF#lZETiKTuN?a&7SoP8_PEV(`0AhWg9 zS)f?9*4s`)7RX>@MqtF6Lb!ekS1kX~c+}hn=vNBM%3jXXYP&%&{UCL^kynPg-6@^1 zk5r%GM5D`Tle4;SKl8nHpBW&v#PXgv98E-Nv*Ej;A^Ez=k}%DS3&wO9u;DpvVhEfc z1&SYLaq6N3-%9NbT_BkZea%hs?~>Hba1s+Q+PM?ZNqCICipp+ZSWvlONa2$n$syTD zoj&ZpZTz)-s5*#pAF`MHqps7dr%!{yBPWf^%K9Gi$>T9SJli>y-$bzeR6Xu#i{mkS zWqvmjc3ve%!bowcH%5f3*HvxQ_-?}`8hr1ANAX=&Rh+ITr7={+%km+nZH@r$_ijLxks;#1@DPafr7hyUK>kOquF|V zD3gVPnjQl6b!*`-bxD^FeMop%{7>!5H8?K(hw~(ry~I`7HioM@&HZ|*imH!ah}e%; z8ETme$cu`BjPpocRFYleu|HJIf~U8jSNE_Izq;xPYwDj*!XK^0$4-lnrIpIh zjbLU>x>G_L%g?NgfX6qZpJEznIqHlg(xPHP2_fp=Lq!yN=s~Q zfPX@$dL8aXD{2z^wRSX#57-E^_q8gUZuMGz}o&@J#LIt;E{_T<&S$GIeR(l zQGQKjmB*fC81A*N-1x$^Hz&P;=T8J-aig!uUKj2oc{Ve4Z5no@B67QiC5zSre-Mry zB`2R~h&Uh`vR}x^#_vYqZTSH5=}0uxq}|5F-`rU666qFL4wInWAJK$$E*5-}=R2g+ z1#XUcqzMaEhzlf&=zDl`jO%2i_t-1m>(=Gc$7A=F^pxUm^D@Dr%Y`4 zj)2M(^k4evR}qXgaIAeQoL_emCYiWV!YdTo(J^O}I&LL+g@Fx-$F9+Fo=B@qIfj)6 zHB9NXaUO7P$i=*liXrTYh!ZKzWXD@DS!8!=QZUCcUn@_#|Lr-DkIfbx6O)VmFGF&} zb;ffubQao|@0-|PsbYhO)Bf*>`ztB`dY8vft-^aHmK0n#VlE@f1{Gf7CkzVJULt&4 z%x}{(p2`2DNxSiGOdElY6{3lT<(y>IZ z_r^aub=r8VCeh5wz>9s{qviR+)_7sjF)|fz9I5!sy4ZOec z$h_9G_BFk`mrEV-!w3inyko6J4_>))1q8#-9&)WS_sH%6YYxhq!|F7?JZ|cJ9+HU zw_YU>J_)Z_e}kZ?*#6pIV*h}-Xog&zC3gLj{F*ehk~5oxtBk(Ah_?fSQip@J50kjK z_zqM8_0!6s-tRFJQfhYp?v#hs<5nMGK1{V5hmKf$5H6=yf#w6)90-i(rMuBj22jO3 z&x}*&_Ka&tOxY{oCqMtOi}JJbMu$_!)ANtw<868LK5oG7;&w2*tE%MY?mkRK?tlPO zf5FVzena<6{lq4Rf?V!FZ+iaRp4H1PY3c7;II{Vr-M(ipbogy-6{}U$9xcm#G{&4t z#9g;Ef0!(JS?f_;oT|fQPo?FVS%w{~wEkn3Ul2ni;tFsbh;+il#3);jGM6_j@{kI9jnrr^UEF_)QJO8j@WU!CDM1)$ENcM4WmONs3Rptsf z=PzL}v3aepURXEnXBV*`kKHY%NWJI_qJ$IuZ}iMq8^ZMU^Abf;Ye#KON(s$!weNnfE?{M(>qqmwUBO&Ka@k$Dqy>pefI{mBr274L7vrW5b=ux%nS1$pmz?S?GSjGiyp@wI18 zmw%?m{=_S9eUTgmMN)S4Poi!~RbKKLk7wp@Lf(z(sH=w?J$s&&6}n0rEHhVk)2v7S zARBpkJ#HTArvzw|$^#jy9wW7AbMq&_bzX~{?b{WSG@Y$iG$slE>b3u}GG8ILtk+w0 zn>%-q){*YDT)-~l*Y6|^LJ$PsTMt9UCpiNh!Di`oovK>;;u)jKeE(Q1+04g09yA6M z9*%UJsO?qZ$IeC@N$r)c3ELl5wFo-;qiN7EGOvmOG6%LVRe4#}w8s-IpZ+i)RCCwTXHSD^1`Qu?FYaQr81 zBjBaeT_D*GmPI5mCx+ie+f_m%dwUq;8NO`O>r7E&Gz>$TBvR*D7jj~48kP=AyXPMr z6VBPV4U!)DpBlsA%^TtP@Z(4`#|mO+K;KkR=Xe)J8^AJ?=n>^)s;-siPXXNM**%DR z98AQe-0R|wKx3?$`!{|tfh=Cj1wh^>BIhi8%PAnGZ1@O==4Es6?O6=&<}!a@PoR{p zi3q>N;TkN(ipPL%8I(!#e)ShsQ4tSyWHokWfGZI-7Ff=LFTe|y{rlueTx;PRJ{92b z3U%TH)^{SsTSzlO?EJTz=LF|GhvjF2PwYGvy5Bt(D-g&tPq>xKsBT##dRiG6NV`pS z+-YoD(SE^(ul=EOykBd>Z^@?kXk~d?3RuVX3ICa*6d9MfFTrI@jV;i?PWsZ4Y|m|D zGhSs6m^91b*5Z3f+v?jCAtp1o1Efiz8RzV6v+;6vnm_zOjFI*+eI4v5cneXe^f6qQ z@ZyI9L3Eb&gfVqq&@=~W3lNR~+`t!Py!^?|Nb#q_%5Lw;-cbN_>8o3^)tc`lK zw-kd;K8Pa&0p)l^BHn_<6th-y3b*QLN}qeu^La3)-IDgt+>P#o9yTFCeY8F@10ei` zlK?#@_pN~lW5_OX7+YI^(ZIyua%JR{WzTx2CZft6@{q#DJnTc0jK6Dn~ z|2(!hJ65Ydthv#!MS1<6pNr2Z>fF`UrE}#9?@G?k z&w6t{Yz;Dt&7xw^Nyc9<43d{8HzUwcu@dV))pqS>!y5&17+fQ)v(%$hO?Hg9z=A3f z%^~<0hjhogMZMcw5ZZ*2p55T>!pH_2vFj)^wZ&sO@B(dy_3-c_ zdR7%HwYLA^?gq6`10c=Wk{CypkSN)!hipXYKhaz;dTcfx&Qha?ww|ocl?$v5CO0Rr zA1vCB!mM@L`V0^)Da{FucZoO=_Rjs2R9BA2Mz%4;+OWIHtBNUF^pjX(#kv3C(A=H# z9HiJKFyF_lL_b@(vzJ>&4UBlQj)SFW3B)7&C^c1hr3BaYHilO_r;!$aXHx}HSbhV0 zX+12_4i?AV7`t#5Od}tJPpR?B*5k-Zn9Xi-;O!dmwiA1vj2o!6qd;l7`=>4#JfuG8 z2&d4F+M#LpAJ38#S(cZ781PZ=$K>#G8wNa=Y7fO#a9PI-xmoa>`Yx~Yq3L%IxM>V4 zzp{7uguNWJ1`9^OS^^ZpgBECR3>`F*a{`Es4Es6oyFnwsm3WvEmMQvh<4lw!EHy&zhS+U+8Hg zYO>+oXQ50^1)62h3sW2eE7irG{j4_^4&asV?ARm=q}OA~g8$Ygf@u0It-nknUyMMK z)l@_zxrpCLay8KU0q$kjUzWUHM{&#Q)d9Rk?Wuq|9>?d?6=;RZ8(W>wWfS=$wcM-( zS8xjW0hMsMxz8q2{ZnAC_BHNM3_TSoX&%vTbJ)F80<_z()Z-E8N2!FEhBjU70KXXAuWcuU&nV6~c zQ;HvN=UNE7KGk)V!(XzkiFa#FsW`?beh$NoLvm10e&@x9BKQ2)>O>^^c3COvu&tn$ zZ`R@5+N0jguUprl%qJo9l!5tUO#IWMD^_*5@us*pdgJmM?0E7#b>QKLJb$TmHEFL? zmHx)#@$m`~%I3cv9$oZ>$SMmlr-9ReBJ7v!Onv4lB6;Le5DP7j|E7rBY#$c71Ilol zC2e=Hv$9}02h!h_`(5mH>2>|=aIiCM!)(BCPGbNj~dS z6&l4O^^J1?JZLDd?|;f&;GQ+H#1cIwT9OghF21Hl(UNsp;b0ar(IWtLu24KHkA<3l zu2%!F7WPheo?&z*iSa;N=S2{G{q)I!ObPAS1^AAxt<``dtLk2sUR^zE-oqYjZs3%e z6L27?t3MrYiq&{?e>C9O-cOk%S_fb@K~*p;(gxuRh#v&01;2N2t<81UwnNC@{QS!o z+MKn!BnP@cOEA-MSyA!!l;EvM^nl#WFBkORh3|qUxo+v~%l-=uX(BSzh#qJ98$Iq$ z1`%~gFs4Ao^>S4fedH1(i8|c-#F`9%w_bG*ZuD*2>xUl8s@PK)&MrB3%!Wlc?6toV zp1h^`44FZlhT^Ow*ajs3Z5#Nq($%bI9Wf@n*AJ{=9X3Ul4SSKtnD!27j{_ACchoYW zX|pHbdgkmdh*2hEbcxfffN*{GT)wiW9tDN@VDKOzQXkr4S9R2m z^KkJBswTnpX0Fu~tZ#3fSX4{L3hJsq?1DutS%rlkPde@C7z}_{;qQsr&}J z7ktDyU`X8XZa7-V3EUE?LK(2AaO|*jsnTl6$izKC%rA#*+@{bYY%<8q=ipI9t1qYA zXp~n6q8WR_a5r=yge5R^oTu+cHHM>`IMdtT?`{w>E^W(wV2t=$kVop}sW zI^kC$tR5NTK`hCYir{q_gv-YY-DeH#I-k+q+U9MxA&k7`0WjQ(9PCK6EsRVUnD9XH&%t$4b_kf_d%m$(~E3}<-cTa~ysN0v>IJ+Okg zP~EJ2GXuN?VXx#uFfOf)axj9Bs%F*zw!!j$+XhR@@+c@M;4rJ;e{OAPjAFOn_VpPU zfC?t25AKyXXefT-xot^*=`fw`&Mj9BF;eRGJj=`F)EXat~X3qI0Fd z=uyoCWw^B<=FflrLt?lfot1Han8CHj!iEGtZ1sWo_!tG_GPjIVUT3o*LNxg!Es}*>5b*PQjJtyb}6!91;-*#ZH5hM~r&6pw2#nc`v3!0wA-Y zW4q}Neu@of)e}FblR&@Ie4XsV7lYre#P_7v)KX{beP#$VD)znPm#=j0VZnDxD`zAM zj#*h-Ll*}{N>52<6bOy<^Ew0rP}24ipnauqyHi{LbJHQ2>9Vz($Dl%?0;8_ai^;3L z3b3LIj5_)HdJnW7z()Muzc__6`P@Gc?%EHPl_xvG+95x`Rk_JjzjfO+T<0^*3|&)S z^tb*4c+X^XUi>sH7kmEhA^+V~ zx%sJ+1EJ4Qg+tPD&piH2)xbCXI-Qcytea+{%7EMy?*5_Hs?S!|H#9J{-b6ZuA^Uio zydR8=SRgl;T4j3l%e&qVpa94+-ChNjrob$Pn{xow3`!7JDcz^XoJrc(2nHatQ74CJ zCehCt7c+nAb32IQHA3ej&)up?Iy`?vU}bayYGgwFgjJh4t#+jnebHUbSp zaN8PigJ(uW;z@Hd*p71T2G5@u`*jh-e0izmtxvc!$8$fCL)`J^CozsRN|s&ij;c1T zx}T*E(17lp|0lja{roNkz$XSqZD}atdlp@$ z?_gXGTMh05n?QXwr9oZTeP21K$UOh9$jd8TIq}oqKfe(J!L?**7_LGa+w1}FzXyupTNe=Q<)dbAmW znv4y9;k%g4&g7L}Za2*+Hy8+vX=p;}xE#iM(2Oaj9R*dl+m`n-sywNEs%(IYKx0** zC7IFsud!q+>uXmO0<-k^_C)=y6cx&^>H&6{zsw2*4KCF(X^B0i2b~lM)D+w!`cPQb zwYyDH#MlN3yaV2FXE z>9jCm@!+o$7L6LsGBDXxa0-3nMuBY`j6_Z%nHHFPJM4P&Ue(~kj;fO{kd=!!Kd-zRc5b->rPp2-r_oG79i90Sj3X5 z$q|`b=R)$Y3#42Wrk6NUIaIN6DFH;9tM3g;tP-#I6s|0)GnJnJ1~jkziSH|?)eV;$IOX2-)hUJ({{Ud;3RL1~mAW{Z1V zEJ;|-5JOmC!}m;vg4z9-+BZps2xe^z-44xOda5!a;D{HM_$P%_;D}T9hxYy?4xf9& zN8F_QDvSxnGF^${mzRIB<9nC=O}FC04Bnw6hvPbBUa7CudQpJ1p&obKkniJp${Z77&<6|}1ZM23xYq3LY}p3z zPb{&BxrN=*5rlH|ot*nH-s?L#ztF^N>!FEj%~xM=H@`A?%f#pcsx3PK(wh%d_DJvy zuU^=dZ7()Wh48;l;Zh8WeEUwa%KOTdg9upYJvI)`U#XDr0vGK^ik>}0NUWTHpi7Is z%}0%G({!wUyE}cjHH_ORB!7DSg?XWKkP2^C^36+E51Jmmn!yzz7m8#STN>RL+!nE@F6&_FEUeWVCfxaX!P#a?pC2iBmJ#cS1UbB-BUulo<2RI zs;L?GWZUy-eEE@ZI=U2ytfx!UnIpe4eE*V3duJ5b7~cpA(D$XZ15|8&hIO?hib9|N z+8f|rAOki)6T?DW`#>Z8=%8ZNuhX%_*~oC0@v=s9sN^{W$^j`M!o+k5kUg|z4n4R` zy$PJ;!AUQma9O4QX4&_ptbC}iCpa$!M7rrb>{~bTYHV!$(6l?-Um9&=YwN$t?l{_t zP}U-Z|8)CAFu=A-$+nfss@kw(@2R{1vLpFx9PZ3fCjfhT%dBbb)sC6rI2Lon=piVS-{zI4o>5EvQz@Qfk#7F0l1 zvsXbukgHm*F<&9M`59+KxnKJ&nu6ofPTR|;i!Vm*!~ z&Pw-&3G0gZP&2ntR6fo_lV|o>>6`dRomJ-xRWDFsFWh8evPnMopTs+f^Zcw?w<|ZS zj>>pS+zHfvEoa$Z;?$UWG4$Jc!;*xt$MdXPg24zBy&hv+2yO|nOZ5p;NrZq`P*Y#z z0%Xvk#?U&6$KQK*!+LUd$A6ew%q3co!-ZgEhJ;LJvj(@TBA@!U;{Zed9w|pzgrM?D+zPq{&f3@PyZzr^9$Wvo#kiH$Lr?? zzV^xgQO%AfS{za_6_~1350&`N1Su2rRro|Lz-yv<@Cu z!=2CE{3E=}nH%7n$v*|M;QSCgnT2tZS`OrXL3i6TD9&Yx(gWDopkF$^%^M99iiK`- zb9r(=>T_fL&-xe;aaZOdLSbYb_ql_^l6e6n&a;y4ixwWBwYc)}#UT>CJ;9IY{~y6m zU&^v0u`{f@N1PqpcP~eu+=wNkCQyy0e^Nyt=IuYge9vk@#*u5GD*G|*a>tPSQpC56 zeWf?hYJl_~FaG9l?=sVxZxsw4F>X}<^w$G)@7jxLz#=lj!l+r^U&0}5=~K@=6#yYw zYzhRndrQknv5IT=XNw9H!q@D;jEHZxpGBtWKL!LQ^Lu|R=vT{_&f*cAFd7))!2z^Ix00->f ztvDDifpnIG+5OdT6-z@C=_PsmXYkBxV zmuk-HxrDk|@ zU(Y+>$sRm**tivSn$s{q4sYOlr;R#ilsM`NIdl=n{=18qSabc}`a;CMSER=sL`h|U z=RBG$$S&UA_IxJeRrdLsC}6sy?m~8)t>|HS9Qjs^3ql+)YN;NkbCej{41%I zswf}jsv?Dyo<6l^B09iE((%0y+HlsZ5A$)wWw9aFc4@uOdaZbXofZ6luvKj&4w zLNMf*GG^ zpSY6ns-(nVM@d^~QBT|NQCvwh6F!{%aTFd?-mFyJsGqN@w+=x??kFB?7H()?VFC>X z(;AEm|I1wKZ|@;oo8(`_;aDFxz2B2(rqPcF>Tz`Y9VX&H$umy|-O#_CU`9S_H~k)= zQY_*I5C(@Fk36;;dT}ACf6M|kV5G|0^)@U79hU1kVj@+tDfcD{=nl2C|4etdpnT+@ ziO-H}&jxtkx5A{$4rn!Okkl%`F{*&H9<~3-j12>fY1pAC<&c6L_JNs(a<4Zg#b;#pHQS zRNY6sV7V|zoqO}ml@|s%Tl&+HHoO+`YWr7tPfR^7Y)M)x;r6Mls-Cl~J@Nvi_ZAy3 zWEB?1bU7GsSk1R=&K{FCP~_pTKP6?x#xTPUT(_Ek;=08TbvHMwZvswlF*#ZndJC*x zCj5dhUDYt>2(=q=&;2a3)%@3W62)A3dR0B)w_1GjQHa8=TT_LqnCxD}lS*nb(I=V_ z++%+E1??w7rVXewL#Ljf35N0C+)30o_y^p5>*}P_l7kt1p+4>ck~KCQ7}tWQTQr5v zOhApATb%zLf~fPOzvj-~kjMWZN~B1G>hd`ia)EYy_U+sE>(^yRH`BkDAkQQn@YU;F z`Sp3OAjVj3iu^byFB>Bt@$rk=A-vU9m&3lEtGapOoc1G8`tp39qmM7yom&lZiG;7Z z{(=up#Mdrw7FUqBJ-^mc*&{BTTQy*LcjA7u>tOj>zqo_U{HM8*+XVtO>M;Zo(jFnZDK%Mu)lWZeF_|gWLU)P44j_Z(I*cK{n~YtT>=*_Upua{K=vCk>uKn;QKUd>q)^wUVATggB05v zpM7GH%%AMJcsX9wHg@fij39qk)`^ufcD%~Mo*L>mmdaeGUsW9zv;bVSz^RjPLgvc{ z-9AY#{I}dsYR7of*f&ula$oc*S|Tb{9q%rqAH1nm-$bo$L)7MBVX32e;NItr*$j6a zXxiQ2qf%bZ7QZl8A1=~Ii3cO8+UQJvEBgTDS(1Em8(7n!9OI2JsPSkd{ zz;^AlVR1|i>TNmK@oXD|6WP7rtddv9=qQ<}@T-{@Xix1M))UCS`rU$X?qUkCTQAn& zuD~Bu!u?(Op09<_3l6gfBL$abYe=>F^O!Nl-M%$AiPK*Xmd{-@!;*Fs%n+KJJHpig z@Xok1RvY!>W|Vnn@oZmA9&X!GqF>7U&9QzDyJTE?F8$ogm$~$b z9A4PrneTWK>)`lh^vp(}@$~{(C!6r}@;n?!o3E0f+x6W(JUo=~tfDCWbKFO@+r&Y6 z(++9kP0vJ|4aV;lfgU7N7$bn*djYMkMQVl0NR)_*V7_f=N(+v;rkEg zxhsR=q8XaScn3&xzaiZr7d|*?uXizx11ts3hYT65QD^26nm>G{**in|#UtR~JXUBt;8(Xw z0m_v8U?o!uH7v0|$2on8_ikbh&Vc>) zeMU^_AryON9`0#ioFFCsoffM21&4NXO%wAD`I(sGV$0m`-aN2WGU$wC!3*RC8n3}Q z5!)ELAkyT;@}ZrUB_l4TO{z2RhI^8O8s&Yf369-<-Fb;FaB z>M>7l5t(%s+ZUuJVu?GHBG|DULqoj5J}6%2_si%SuFQYF9N-hM2>ge*^}0Hb9k->;9(pYffk|KK9N9AW4M&N&6g|-$@aH(^zrg)8A4PWA<Qd0w=A*!aNW|;n;JuA{SiL6`?L}HG=nc2XHXv1!P+l(;?37Ja_^Uo;&1w?@Qm$V zO+HZrOLt=>uR%VD{O72JeWs6nj_M>oQiIb@6X)|IRwF7i9vW3=P&LR5w%?+#^ArPAF6DRe67gNYP;BZ5zrQOW3ZN zQ0IJh>jqx{8X}asT0s2CesZP=W!3ew=IC>WCUYiGiZmo_>lF}nh55r2cmvec;R{<( z&+=`m2nHEKo^bFFAwSilc(PL=(om)?bN92v3w~FAdP~CLON8SDgDj=&0~Y*fmeOkN z>-*YZVo=oK@uMS)`%9)~_s3wlX)uJ3hN0`%N)F~M#BT3aUvW-x>5tdt7NFNFUOlFA znwT0BRL%~!YI5&ZA=fK79{E)NY7MTRxiiBm;%c>K_OWJlQZuHrzm_}MH{7**WLPvz zdHN5+i-hbZs=B8Q$_*OfDHsP)mA|*}`POmlvb9+!cf|SQ`^l&yYlCT%mI&wSv6t&%lm zZicv=tY<+or0B`<^Fn$a;c@Kup(Qv+Nfzd1Zfg3u+}~$6I{rJqpJSXh2zR5WGC{Sy4J5E z#BW6=o9}e?&Fu=0Iu?BFnKK8h?Yu%7Fe_uytlz#rN$VoZXjL=iIi?4Pxq%#JI8wVk zy=+>SZ2Fb-GRdO?1EHJCV^1QWSP z7*9;Em4KU;LBY!t!!LWz@n$c&Rr7%zY$%cT{5v?~7Rp#g%*GhpJ2!aL+^tE~DDm4r z;fh5Z-XWiV2UWt}Z_T*>j`PX(Sz*H*%ZMqZj2H<97@Z+Mwi013vk1d3n{t@pDzba8 zn{`WysLCxzUJ31-E ztqI3q^UufNc+qFAe5moDct2f5Nkcv2@2Cbw$O2Yk+WTo)$yd4Fp9T4WhS>($=gqWM-6o6c;W&?oselP!hg!z=!4Q(u%5 zz&q{BkC?(Dydgf;MT-T0cdnODjTypI-(%k@KRTD;HD<^cZS+Zge5Xz+%RK*8I`i2Y z#$h+mPPm46t3#n&zX+a?yoJ=Lx>2c!Iv zqW1NEC}=nK3RCbu`MHD4Y3lx?I>fxim%EQTlhsrYY0P7q22c3`+m?u_9@g?~!3gMOEt~I5=k2UOt|gv8x_>6V4{B z3I*m$DfdFLO($x{_Zu*Z1U26#d+_eF^%Cs#CwjUD4jfaGutn#N0A2#*h*N_V<%Kuf z6mV$#N!#w%SYRqm57|oJoyqgeU2n1a^z4>)Vq3%k$v8nHtC`-)8y6V5`))Sq6uU23 zRon;0imrrII{WraOy1fzK#cD6?Qe(WIQyq3d}<{VVVyAxp;Z z|Hd3XkZ!hs*QzK+%!_5y9j=2s{BIQ&7*NW>KlsehYCPEroDS}ipAAT7$|q(b--+ID z`bOERPZ1ms;ldkf_0phPVzX-3&!0Se*ROH6Axl!h4E?R_c+)0;SWMAogpyHS2E<>D z$9o86RBZPI_`NDXCB1H+4HfGq6EPQ_?D<^f*4)yG&HQJkyVT0)hUqabGuxtu#W*sP|hi8RcE~8?3u;>ikL6V+*1x)7O(~!U1TX z`%hT#@2)XeFe(h&G>+Dx-n5=Rqubsa1TieGDwdw(?R=}ewSwX$5h&<_U_%|jph%wL zZcidbVpaeetyhoRP;E`Bdd`ARygAM*f4^J!vtE3~B04B{L*wN!U6P}4p3YX;i=Jm% zBNoC`S=%EPT0*@8+%S0o9Ctn!0fX?O;NMSVDQ#BUPe%5m$(38f{>mm0hiD?=`@p5caOi0|)aNXr22X)G)(Jg#50iDmBQ zWYvATIu;>IKo$X**M}VBHU~swrXh?b@{H9R7y2gG7mB|{6!m(NHY7c z0d-^?q}DDg9AklK;Iw(<97+{0?*a>8`L3O?u&`H;3=IOSrX;Md<;rf4&`KE@b}Srm zfP(TqWF8kDDc%vPf_Xtq4Qj7Fd++;7m}7}|j=$fuB-hag3Z1h7Xqc-tHy#PpB7eYT zLFm^s!}`@NGQ}%=)_cb(=TG+-lD;rT5_#%44rzXHf9@TC{1Heiwq~D{A5w!-(=zL> z;LR@haJ4L{K_T#BD%ruKAKo2ezL7`nm)X1UE!n-Ac&BP>V7}1#i0~un%U6&tB`)|+ zU5cs!x>P&7L*~>qIsWxb2{GYAS^(x?;f|pzcZxmZh(*Zfo|Rr%?4D#P&sbH3ly&t# zr!4Y7^rLR38ZMF_u#)Du-}eKyMkYrIU%9q`7V33k3B4L%!KBCXob*N#SSV}Fr!I4_ zhlmh%*}%$R5fmvDUAwKY*r}>9#31m6cum=fu8pH&uU!(S;;0dO4c ziACP3!v;16RQQ-k@3EkRP=MXJMI`7w^d(|ppISUTj`b9ny?!%;8FNrp`%(lu+tT~+ zsoirsR}F|Dcu|E){b z7E*I1W6J@mSk%-3N-o|9Dbw%_J_?EIk9c~FnfK>f!qE1m=hW~fB_@}~2kJY#`x%6A zbUfBy1hYqh4gHk;`YvQcVa;gB6c1<=CUZLU6l5evP+v3ns2!nkO^FMOyfHwnESuh`Xmyeq&jeHJaDlLtr)tae^Egeun05J8pBMnfpA%A-X)@Eg^y>VhG-y>Ux0~q0fHre>^&seAaEs{>@HNw+TNo;B@^3q`ar;8T(l1 zu9Q4vW@D2|d>Md#qT>r~@4k>9H{?WU9@gHzBgdGr@316-eIf-s2c$IxN!7EeWw=4HLZZ0<-dILZdu4uk$1drV9`-rNK|cyXraUw0)t6tM2 zvVKnI-*{JSw&RLWq$REio=dahs;7?!s1KDcAmLKdQF)r zFz4xMyvMQn1Tag;-g+E{L7GZsc6X(<3t;~r+cTprb11_rTj*+C6=b0mV3{^Sq5S$v zq$?Hl6n)Uhof;^2>mK0k{+gk7xWafa0KHaG0#3T-=P=o;<6JQ0UErIf_*6n?5U71 zG>7klzlPglsOk3ck(|@-78FW>VdN@nGUPtVhD<#476QUByiJFPI74h&Q~XR$%)u#d zJ2qEBB|yE=ea-o?cLRfMRD%X-TU?ulp5?2P>Q6ZV@+!FX7%hhkjo^5Y56Qlz#gc!-;ZC#;}7)i}kdQuRQ>_-qBL&X$lWrVaKnkT`PXPL!L?;fk7+SB(rctH8GOiTZi0)6tgf)Ay^}0nqgDyR)PSv2u zHqQNFA2SIo5K6mm-I93g9O1OE-&Ijt)h!w}i*5}xr6WZk+DZ)5mznGoBBD3iB|5#< z74#T_+Bu=Mq@ERZzw0+EH>DG*p4Xs+6V_*s@odlGREg%4`QC3ZV(OM24LPJ&27l^Y zyA!<${qn=i=n_rY<4+#x((aI-lFBy+Sk=8`wmPEZ$Frc#p}Vbd21V-y%NVh&uZNLm z2xso1-+#Byei4%G$<4WYl%MXQK7EIEk}s}nlO5Cy8~~^0dOFi4ioFEG`-cQWh04ac zW9%CxOKld!HT>dNesp&eWy9GM#D~%~_~gdg?R3ZY(b~)2oQeI;?}c@gn8K4x?g8%z z24;5Bi|M|%+2N-%5sA;Z88I0Xt_L@>A|LNUnTPe>*_=|$##B4T>=!v>a4I2>GBuY^ z_vLp{<-}zutw{~vI6COR(vp|iT{kyorlIv19nrFQTQ(ZPzdWfXX2!&B;A)fWnK&ZS ze2$)z=zslEVIkIEk)B>R45DTkl}N_<@5Om3GPj@&3X!qdoB%{U90}wn){~1cZ)yUN zo^D|B(jo)WeTv@rL-)y9gTv+EntmqPlKFgLjE|qLLB$aF%ebm#T@wT_IS=Mw|2ka! zdj!Utt@`Q5(PiBM@2%OZDuElknZdz)+A^Q}sm(e8%5@>TzjUPdiSZPy{pcFF#3$!m zkAqUlFf?g&l7$7oz_zMONteNu>@m$}d^}Yx?(}9}&~-}Ud;rF;t;u`3!dg`Vn_EBE z`qpEsuV$=5^;f$T68_4F>z1qHcFkWZ zSx2q3*9=~44)DCINSr@VcX>%CQRIyEk3x=dx3(ccIoTSHGnNo3a9!Cr z4hG?EvY0nM8%?HHT{AsR_i9$cI z_-Qr64On0i?SDY+l)2wVMX9k6l7>G%`9t8}ro^Ko`R8pSzQXlC6(spW&Jh8F|qAHhib`S@+*vFn9wD z+#eQgsTV2Eg8Av|?)`5ahF+^J*0IWk1yZlw%k0qILq-C5Y$HJ7%F6E6bno%!CwjvMW`b!o6^a4i-*GIrtTAg}pDQ56wI zr9kz~dg6C&!9OkNFeB%)dtsAh%I9B|hs9rsenn$W&Ilip03KZW-JISu(-SPBGry2=p{_$WA zvB*bMe(VF~KXl5SCqH35(WBvDq#2Hi|C)B6wvNwqq9wuFq2bV#;q>UEmqT@p8faO) zQ#eLOlHr9YsxiPjfFh{rbR2GoOD7ECf7#qIxWpiT6+gMuz;X0n3~eg4q4bEc!Wz85(n&G)sDcq!Aaz zw0%(brj-;qo@Vy^iN2G!Pyft3GldV>Iu05AA0NKyHC_1zgeN+6>)v&GVt(?Z>|Pk{ zp9UA-FSHogAaIV0ief?`FW@eyBb%W0=eyvs9O?6GYp9GiV~g{i&|5(0?1N=2D#a%f z?3??bWsliOcp1P&cYv9Z@%tL$;IbUu0$tOWaiTlal=$Woy3Pqi+CJUb|L^cJCy#i$ zU7EY#YbB_&bn${&fNh0-Pk`@}= zgu#U~FpM2r|w5UwXv)UbB9e0M4>Um^o z9vpx#OM-lUxr8fGh?U!455&8!-O!gIGb`9_CA_gvOY8a^>xct&*&>);Ox;-!6Eca9 zupKO>$Cw?<*j_k$>Zt1eDIs|q1Q1|)nB7WvlQ-?1ly8%6y60Ytma# zs!G*fAS}rb2ZZU-*~{ex?ZDaF+ZV4tZ zd%smM$+XuM+%L`$dLS!+IE2c;fb-2bWI7kG=Pe2Y#X+P zw~z8sZ~rj;74>U-Qnszu7{uWZI0~U-XhP8Bq!k1ac+iZw2>{oZ)U2JYwI5#PzrIr7 zuSZ1r^Io`F2*^kyECIMR6ALRL)}~-BMC$WE)-IAr?N_k`X!`U`8zC`dKmN+f)0#Wv z?y&`1zb|c-m|aPMyx~-a@+;G|%vRWgi$URsn4i49_Ck1E!pND?r`!qf;?n2dsEw^9 ziVuEr8rWk~ce)Ita)mI6$9#2^BImy6v_l_N>QS4AZo2{hLtG($3@Jz@X4@hhQ==t< zhK$^V&C$n?bTaI{b!yoe-R{5zLIwcK4A%D!i@(rQUZD*~oY`z5PJMamRIvP7^D;*~ zK#)oZ@8e%+AfGQAV9})UxR_Vd>oda+ku}1u5Zx|j?9=6Cc+kls9pz?F95!%5nU>3N&G{MjV=4;e zG1=GUL_E&fi{;Ves1Yd`WRRQ%j47-=xk2tD^w+;RVy0QhfLE?5_K;a8%rdbl<`odv zTyK>p_8;3|1R#nMpLqKb>;RFZs=>YUG?r?EF&iC5G&WWcI>agElA%MtXS)A;PCokD z_Glvz#7JqE@|YON5uy(IT$4~ALat5Kj2XG|gmMQ8m}sc_fB0O}!(*;!NQ{uk_q?z4 z+6s9R#HzV;kWEUjIn>SaZo6li98#MF2ueMwCh$@Yu~K6;FEJ-UfMdLva*&LFzuA}Q znE zY1h9jH;VTMyz2Gec-2xbb+I4Y> z^$Hfaj>K*C=Q0ClT|EH_DnAd^T<=L4VdgFlF1jqEx35o&-vhAg<1wm9>bAp2Np3(* z-q}~R@yUVY`Jq`rr?H@You0K={|rSNCk*=IwoEtWDe#z+wR}7)l8gtGs`P9-8h;s| z?>fsux8h9-D;YBa(AF^AKg1GnjLt=_!B1ThE($`S^B@q`TmJAcG##(pu!?NWHqePIU#P_V{+u z3A|0<@Bt0~_){IS^1a2O7TH3?=d-r+BiKTyu0Y z!O+!>4P znmxcuA-sOt?Lq+h2Vb^RP{t)LsTOqVm?V4)fpT;vIYd91FcU~^3a9@UyAu9@Kccvn z^|*V->$dg|6lG=j(g*;=2YSQn2P%z>Dm;qL!}|Hf@i^16c&GD?d-d%DDBJ$6zBM!u zwH`c{HJBgtO)M96!m=gehv2B*CWti9JW8>a9d zuCG)mBH`^j$tFshu~Pgye*F@&uwSJrb@VXZ)cx<9f*F6&9jjVM4Q~ZWrjtON?6nEeNhcAS=AsA!D>rK+KE5L=D@dH z0N$4Y!Ph(BuxcGJG+kSP7CxH5ehfTwOjY zYD3N(7CFi^^=_meQpKf(4tArBy$ObG{U6FD;5_EXvB!xT+Vb$9;$N?Bw|mKqDblUM zaePrW2vmFLMPQaJ9J~Gsf5nuCQRc-zRY~LXWyclKV8-Cm7z#^P$UW)KfR~%)BCK^c z0TaL3xjR({TmsQQ}rk5cmKg+fu$wt3C$8HJhuc ztKM2%i$PuR$0W0?HjHY6Sq$;DD(?!sR~hTFp2Ca7#A`6W=6k>G@^NH+gS!TWraUXF zN!51ju_P}rsKR53(*Z42`~zCL{ZQJF@+^DkAnhK#lBdhO+wg?~sif!nLcX*gz4xTw z{sRaZECY5YJfMH5qFV{rSjE%FJ}RX45}04RJFb))h~G+HYi!tKNVxief9R>bWfw1H z-MK0lzun0wNJr_NzMOE29A9kLb6hP};4 zXx(=M*WZ7w>2k>$xNn@$MN8(Cx&9!4LE&-U!#4|oaj(8R|7-X2*KvM|dnf7mv#-v% zo0J_D;+&o*2y;#+9p0ZhXjokUO!KlC{AmPb=6?r02+E8}2m|FK8Q#DEo9kZMleu*- zKaUdOAl_cv|L?U4ne2laoYLv<6nm#9+O1Uqhf#d`XB-yGgEa3meQ(cn{G2&y?l%og z8vNa(kmtSPrQKd9-HKmR3b_mb`*=-E=y>*BKl(A92G#SJMlHf033EpoW@~?F= zR5!o=1qv8df^!$J82Xw1joHx7Q3cwktd6__J$r3qsg)lBbmW3CQ4w?4Z5#4y?=O?z zkEYbJ&Q?8R#&mk?v*~;+uo!7P4?xcwrlI+N75({l{ay1x74%tK-F5gqQ9QWAhp~!l za3)GQeN$;B`gxXZw%e|xNs@x9(i9h_Al=a` z2))%(=R98_-{rE?v!1J#(pSqhfU{-{j*X+C1zt-|>$e5ba*PjXwg(|Itx>%SM615L zVBKQZsLwM8476{rq8?qipPVDXW!`!0zGC=I;;RN3e=~vj{=fwC{$Si}z!Y(DK6sB@ zOK)4!0$$NZvc|z_o={mife5Y%-uxOik=u8HNiq(-V&|=nbBJf*)Q-d(^I{;{Xt9Xe z#CZD%h$$?SlEK_Q781vlw*)s-oiCmq=APA9C-CRSAdcR$rAHhT&Cutcbo5x~39T0) ztP|C65NO{)#F_FNy!xggQ+b0);Y#i zO!C4qfkjsJIa^=~Z=n6N3#w7pQ~dm}=uq$78g$#%On*^PZkRN^M>G_=Oa7bNdPO#! z?GO0yw;&G|T(2e;e2J*I@LD#2r%0I}2p0tk*M;usk{NCyY2vyX6q(ZOk@zhZI?*qV zLsoJfNl(nGeP7Af^zlP8CBcHBqm)0JE{x%;rUT#eV?00@I0!@fHsEhVsR2x@7;mNX zhbFx?54CtU1CO#g3dusW}9-XCganR$3;H}=mESZx9 z!iaVIV)X%z6X*R7f4g#kmR$f=sXM#0(eRmZNr657^~hQ*ArV|P_2YikR?ov4OPFqC zdp`$ihKY&C6c4O1EFI)HcO#$~-?^46gXq@P7(OB zDcyws5g#h3d<~@y!ki)Dagw-yZEv5YgG;QvwDy_RBZgU~T(UxlGT z3GJODofW1)e$DHJ5GB_ex&&b&i!MdAE>+4FYt!O1fNNqkP~1m_Uci4(h2e}G1qZp* z!u?R--58oNDsaWHCSNeJ%qHxy<9JCQHmABnq7LAb3YzEo{Wv_lkv{;#vCw)a$e=vT zO&XhrVh!vd;ighO1y1)m z$~(2}1l9CM^IbU!+v8_^+N@w2@kKSs3mykkHRPH2o0!%9z%)oD!vl*=!9CNvZE#U* z_cIQ5;J{uE#L)?Whl>rBv^A)O{o)I1AB&w=?@H#i{USadh#r|^{`U@>BM`l6mwgGj z1jlbcrnxoUCccGjW$E2C;$*7N{$acZ@K%Jjs*zeXj-STjk>HfFRy$Ng|l6($m zoc7)ma{R(RS(p~Tk`I{$V}j@){h>ftw&h0hQxY1`Lw_RV?DDWKb7|zGJX_ z8>$&A__?ntcsWjRa)QyZTg@SmX$US&d_wrfH#Hq?tCMw~1faVxo`eWtV z=n$y2wE2IHA|Fj2T5;E$9(mIN$28U)*L&g$;bK7|5;n(*M*P6 zAcbzrT!j_)4KN!|a(o7Q)Wb3Ag@l{f>vnDOpw@|DoPi0>`bEqCir>vHv=}QiAqsWH zsYCO%MR)dhDyv``wp4_nvlysBjT8?V&I@zH^*aSix+@kN+Vk7U&q*LeRfaGzIe0Cj z-`y!FNX@-*5mT^mu&P%ZgeuKXqn@YoHpC-L7AgXyiE!cF*?c0w>4fT<_KZN zL9_A3>a!}rS^Z_S!bAxs=PJJW&JSQNmz-VZJ})N(G@`TBjy+IO67$|Z;{Ab5AJCa& z%)e237`JD%>SyWj7}q;M{n8G4%swHxyAF>@rPCYPgss9jE5NKMcvd~a{a2n@Ey?&s z>+RBU=6ESrn;J>3KIR80C4M$0(8_bYtJj-M|YN2=ZkMy~*!=nMVi- z@#0YJ8|STVwc}wV=sw^A6Qx%tor~#H$N7nls-7y4WJt*)Ae4ojhxd-RY$2%dQwR-D zZCVFSPoTs>7-pcC<#2^ZP?pe z0CtQy4@`>f;)nUF7U?Z2776_0Adc%|L)2~9kWIooBN{k)Qw0X=-g)k)T3=~%SJM(6j|P8|CVEJ%rDF%ufdUYG z%`@D}q8N5#_g))uGZ6~)tu=XF6Q zzWQ)3|7@SyH%#UYzorI{{_;%K6Kq%s@T&|trCxk#8Ew~ALer{$=c0wJoM|2N<4mG6 zm6S@+Q(xgx$zT;m!i7XvQL|qeSd9h~AGFn*5!{am)`%$a=i30ViRN@HavV9lJ?OzH z<~Y31Ui8lB3EHkH`v+T;Yllhh@5v-NIeXJDn=`RqZ2@2JSIfMkYNe%;y}ufon%2&8 zdtG@?@$P-&Om4=RLz9{`dn~q&wMb%nYn>-R!!qGz>T8YQwHhhD2vCXEj0Ch$eAyv^ zI)!_)a+F&3$Cp4PjT%kO%Uk%GC`VCYD@BQqyd3tJM8%gxg|moa=FE9cBU*>(9MV3E z$tOupN`$qcA03rfr*@`Ls>RFMy^2mkXfjc;-=pXulE_<9Y(`&6U%HrIGQ;jL`5=6* z2Pl#A0uO`dKptu(>&JaUOO=G$411b%{nOiw< zi4uMp`vzcFGnE;7@?oA05zx|p+6<7@;7)G7*mAY)E{)IJxtBXghZ!dTzcp30A6g+7 z#c#Z3OsEFVH{IEqFr#?HRR2sQFb`M6Ea9ytTXQfDy2^`;=5n&f$%4mdK$mr%0(4mh zlxK-T=k}mLtf>BK5a)GZe>r!;usP9Dgxj3y_H_v-Z=(Xs>}f#8#+6@zL^TXNiNLgx z6BZiBWE_;9rMTw3G451Daq4^fjd33Hgq=*jz9+B+gxnh;&-xHn2b$K(U!)&VeTKO7 zB6LpdJgqZz%Pul!)q8!-Fd57Rd#ZeXos;m7@@h&eRUTJ)oThW{-DacY)q(>N(npy; zEdb)wkyo4=GxoaNo$Yz?BbuqabaVvA0_O9)VCzT_kYtBJ$|CWi1zT@ z6~fdE2FxQt0K_yaR-jLMhBE6ESAgF1^doXS zj+p`vg0M#h;q)mN1JGMgN)V$(m=9r!v}dDevQvK-^K}v+AIQ-bhHC=&AyPVp3U$ij~;i z%g)CtWn|_g`|p=b&Ja8|rLI3?8T%_txC@NLV~yldT{$PP(|S>agE$o{OCEK;w62jt zn)cxUvVwa*N1b$c--fl8R320!W0P`;{3Lrjwl0*pyf-sces^ul;xn=J6Ly%ryY2tq zQZj*gc&{|)&r5?$bE!?&0d%}SY_H-mf=Iu*k`iokKC!-Cgk7%f0|N+xRpW@a>%Szr zh)wsGhIXLi1DOT1068fDHuU?H<7S;CP}9k0X~!)14c|>51dxreL*v?&)29M-(r>I- zt^*Hf0Jou|gf6r>9ulccAX=jk%ycp|pF=lcv3>)jvgwy~Z>0%UWuxQAI9)89PXepq z?|{Dw0e_~);PLy264Ct_FW8Frx?)-0ULCdOcRoQ@3}P=oM}sO}}u_*l=14M1th)k735jCix2EsTA(uj!t zcO#-cecke<%IcjSoqP-r7K1?4|GEJt_fVQN%LlQl65UKGvcHeR`|r@lhel7afEL8xX(iDaZUzKZF2& z*89QXrNZL2_>*Ozq(zxCjgkVyjIdL9FFcbBFuGc)rZ;s&-#;q1%#AK9Y;BGR1y7)RMm2(h4) z1Z=2d&<5@@KPsymMgR-81OQ&|B7H`1d?S5!a|5CEIF3@3U$t(GU-j-MyDY7W)D&66 z1TFwG%daGe^ZdAVa@<|iu2oA*^$s*ZHQ){%_v-o@SC6E1IpbW!N^Xol+XYwoaM~2bk*W<-@`4O7)eIgJb=EVgj8F;f% zlZPWSpEHw$1fr=QdXx@Bh4(_wuGaVFIjXmUWJ&|TZ`3tlYO1w|8zZhzH^zuzdb3c_ zS;zf+$a-l#Eel$?*xi@Z?C)54^O@6M#s07xlG~I)LZmf5Ksw< zv%*`tNnF-Yh5`>2D}&mv3j^R;iqq6k~}efoxpW*-)}Ck1;B(xaCQIN zKmY-wMwNfw{}FD>n;kOwVCOICv!&@xVo{rpNW^aVnaHgh?g9dGu$`cG5z6FCA00|Y z$TkM%y))OiaAiPFPc{F^3Wx>6x_{!a9H7Nhk&L3?L(xTo@TQ{1fqLQ z{5@+Xhs&ls$q(0dTo%!VjyNGD-9sac0XkRDlD08!c2ru_^JQMsvN1y=MaEe~vm|AO zT7%+jcKYu3R(XWj&GuAkDm~g|m_c}LriYs!lO2hW$iC*Ak3+vTNTb3}zaWoH9F`ZQ z452}Yh@ZLzz7G1x9J2X2Ew}_M2MmwtveMGRUbB{u*~=n-DHrAtF#>pyboz+@ybp2M z8gpc}?=Y|!g<$uN;1Q?iPb!(|Fe|ft`geLW?|o7?rDKC;7^8m6e$x^K^Jg!0f%CV&=E?6_wa9pRG;bkR>Wd%|n+Ar$ zfZKCV*f)D_Y$EA}V(_$ingiHZ2!ZXul4H9aSdq->{MU>uLl?Sto~?Lb5XUnKlg4M# zo%p23b076eF3bC(X{R0bu|ntK<)36`Oe6}Sl_n>^H(LFtrcnXM{D+`Zgj<=rqs%ASDRU#J3wWVkAumVLL)27+a$DAE0p& z(@T5qwHl9D)%-uw-aDS^|Lp@uWL5UcChH(8*(0-1Bani6$;v6%x zvNKb%B9&40$j;X9dh7GOzxVyU@5k@=$M28&pz?9v=XzbQ>v~?#=ks!u?87l0-KB>> z;+Fb9gp}}8r6Ft=^9HzrZiBLT^CvVUN(g82;7b8Ee^Zdt`$T%aklfg1lgo%ovXotb zXyJJH+2Rq9tfif+p3N;reVh0%s;YhtWN4}erxpr)U$5cgHtCD!?mb62fY!+o{W1AS ze+oJ|G&_tcGrHp}?$`as{Lx#0(lmTQcNPk>tktQbxC@0PRAnrVO>rk`tlyMhEN1+r z#;4oY)y=Par|wL27YrJ9Nf5_`Lgh`=rkr);c0kde&!QeCFX+!Zpf84rtesIO8!H>? zYC8!g)^OpE1pJ%!`^9zu2y|)99MrFE*h@|K_BZNG9kMF|(lnIlZwMfD1tm933+pMO zf}vE}J?T%>67rJ#thS){Y+oX*gu|c zk4~wAs`PqA!$sMG-~l-z5q8|{k8A5`zCnw|tx2lND=jQ#Px z5AN%YHE5tuFBNlK3=^d&Si0n^zGwGly1Y1366>z$^*p91jG)myvgfMwENnY1Bf@mo z%}8x_k#t*n-RwE{#Fw=ZqGXplZHFb=lugQlw%ItnUsM;NAJ%HmZg7nUutn&u~aW9sM>tfODpNSk! zQCk5`Ykl$LNIMJ4=h87Yyy?=UeTi=K_^ZEOY1x`DtNnSqI*~mDiqU4Irtg=!R1Meg z4n6>=WNje#rIS^kT=@fGPzqDYFV#15IbcQ&i%c1|0BjZ!W^yhAH1R!*&)w%&aHJXx zQFIvb9l^C_<2|D8km*1H!jMklv#;wg^SE!c?0Zms;u`ZW^L?~*8$w~xm!Ja>VT%6^ z?k0FBw|bp~v1qOcbn_MZN>5K*aefg!ChsoRsg%)Si6)172t5FFLob{F%lwiCt2Q*e*9B>+3T-^W2bp@R;szx?OSQa1U7t zZFV@m67wZgn8RxJvX{v6%Qq>B4RE_6D>a&*lzNH|jm!o_FWL&$-kuDR4;!7n<4pB+ z`;FUh%dMWBFK04CkH{zG8axaOBLOT(gwt^Gr9N>m5XQg*;Vm~0fkcf0Ump*s5e0rb zW5o6t6UPIQOY{-w^!VrdzqwA*TWLp_>Ls9kiEiJF2{)s47U5;y$K>jXnl_@=D>YKA z3m&0Q#G!8sC7h?tG3&poQ$gP(+(6h52&p5}*06|8@e(<0b$hqQ&BK-2yxKK~U{O9h zI6|*y#zc3eLD%H#68kdMZF*JvL{{pep%Jm!-kYN-*=oOpP=_zIqQq8gd5_6#m#f8W z^v_ByQUvaxW*4iNTU@x+t?l}~wZ|{?H+k&)KNkSMWp{0BlvpkABw17}T0do$iiemc>2xpRbXpCLP)BgcqA&?J z)msTP`TE59v1mW|Di9&UIQR-C5d_Ct$s8|@5x1-mD^LwcpaC$4TNZAQe;D^m{O)g_ zu;B?W|2kDfyHc*>l8dQw!IglE4U{}k#y$)G7`)X7@Sz>>;rY}0w zMxaqKo7B|8D?*itLN)()_g&L9{;TBM-jk&7?+EG&L7*1hu`i~ttg~2>V5Z6siX!KA z4vRWRMpxF>KHY?$y=zoF_`=!p>&p^8OYtxbN#Zkx{Vaa>IY!=ca>fjeEp@1#JB~!V zR%;xznVDJ4ho!)xH4boHM*)KI7u7Fs8HA;r>JN+ng88&P|=Ube|;w(y7tcL!T*oyZ9~ZO`49$G6O=Ro>qB;DVXA z*qE^O!{yNsW}7nsFSU+uW^kZy|Kxoey=z?_y`A&QpMsY4abG2O#>lHnI~WU zW-2b&>C^GF-nKtyQCG^Z;xUWd#-n>KP*s%(2>d2-14Q(EWl%&Ur|AY4n&Z8ut?``8_t)i%_Gp0P5b{2<9vy&Yt*K{|%g_t8POHj2$WT9U ziaSAlMwV0leGeOXwt!+ZiHn7D1QC0Ow>l4*hlzqScq#M=kRTYs7ucGxl3GG_O`FtQ z`?9E}SB_2mldyN)b|rMDbbgCvuu+BuPbY&s`YQ{uW)L?%z}(4BI{YjxJJTL3Nsa-o z;au{lNKerupXi}$Yf{DW5{bukd5ql#3T#aeA34tR_13i%5pF|tP~wIRsgZ+#*b)DQ z`1QB2Vum{Wc#;tKl#E=>ia?`Q>Gi(2eXHtTTq~?1+yR5!cYd zN1G?p)M4i&DGkr)*i$g|@Xa`@f1aqeL%aO23tg+~`t#G4QlWrSHtXuei?7x#6n}_C zC(fxlf8z0*&bqty5%EGr7RJsU?JlsCLqMkT@1jL-`3#kp!{<1TCxoydfi!0N*)=pQ zMPcUJp)vjMuc0ymF#0b07#J7yVC-9i$N#a=bDym>ZbS(n!%-q$-QE|%WK|~Aim3$( zR9QwR^@uNIw8WxMR%&XQc^CdDGhBZ1>+%OI1qXN>vf)ic)G0W@WdZ)k`XZT2!nt5@zJjI>wB}Nbq~N5L&jeR#LjvrL(i>sR$;YyUKUdkS9Esh zoyZC1dDMtM*`2);O=@g$Hm3rulV{>~P81e}T1B{dW5hT~b&Lkvk|Rt>qj)kd&K)R%ke4qa0dgxq!)AY5`q z;4RV=m|0TcFZ*qNd0)sXLS}X{938A`rf#{OBF9(Q6DI0Sn;4;t)fGa zcbC$lvL9?HSR1YTvv<8A-g0iZCcq?Q9X>PUv2x@OeZWJ@gsCyW;#ksY75HwDjlIX< z%%cDf)n);}nL7x;1R0S;e-y)$k6>PA5DbfD+$UYs;zC}6|JY+s=-pFq{;D=c3n)B_ zG!6;8(MZRvCzy^8ciu5+e>c(Dn;F<6?Qos}ere(t=-MAguAbhba8g}< zW?|+n`#+?+=RR+A%5+hX3Oe83Y~luUGS%*{yM`+alGON(@mF9ILzO(IrJ4{%20ju0F)MB_B2qY^kXq z?~?x+D?=)npI@IMt)1TJX5o&-( ztFecnD?U>JURW!w3ANE`Hp`!v&?m0|{Zq_e4T{@|GncB80I-gUDLtekQU@yKHlU5X zkg>P0)b-cBe_R0m_x(zP`_KcYb}HzQq$93g2`-l(Px;Nb4i>OWW7rz=-DaX2R;OyG zv#HA$bh+=ZD+^g4o$D6`oHYV*O7r0^yXpj49?qb9ao?uGRJuJqX2S1LVy$2``sR7W zsLS&W1J4cc14ZoQ+{?87k1StT>HcQ>3Y&_5SuD4jYOs94U;hF0F?a5ln8i1XszEO# z-Y$hHgH&T;l;9VQ06~JkQc*tz@AETekjC0g%qzTd==!Ci>Xcila0f8!Kg+UlDX#+3 z&tuW*;gLYMJ4zut_?BVXS4UT&Wb7V5a=OgrFj#@+Jh`ZL7d6y%^cD#aUKT;;{fj^l zoBrS2D2UfXKx{n5rlsLqtnP#tKQ42<_3=$pI%uc2Pro$DdvH?xQjNd2n!3(b$QF#esgjy;?E?)9R6_i_nnaSfnMP*gWrGry(c^W8k)V z@4}9yhzHYcONjXWzd$SiS8}+=KDJ$hvtiKW2N<_Z#^%Mel393TqNj}M5&OR8OXnMd zcAx#+n#ve(ip<>yf3UF=%KGUKn7|)T)@Mq~F|?RuyraHAmr;qZZYcsqoMfBWOEO76CBBIDvTuC0L%cx%-wG{;SRvvy9dUZ zCouudf63`0>Y_T6s=&?yUKvOb{=??$6oR+r`<@giK~x9I{U^S0EBh8JgL%PrC!%#t zdo50Bn3Q|v43CbPY~qBs7_EZOy7HUcKElOI;QR_q<+$hcIhMHDT1i`&i4inG!d_8pNb8maaI1_ieo50$-w!nYyrvV)=~x;C2Ef z^^CVWO-8^?Z=cG^(Xj)u^Q+tLFPgvqLkHo=)&Xf;E=zlaABJJk3sUlN`vG92gP8hP;x?*}9@7+w8d7<%9S0Vcu% zpl3@1-A7JFM}2ZkESmdvC)~*!cbGBjb3#ay(28nefq&pAB$wo~@U?woBnVV$Y&b56 z&3{WZrSrje|u?nE2hytYsA$#l8({WX~I88nTY4r03f z_D8|8()Al|f3py^!E&p?dJtIIT8{z$fJ(aLmT@g?TK1l(`We^DmN!sfDYW@m+9A60 zsa)6B24`&&RZ4KH(zUtxSP-$Ej4ZO;_?3UfQU!bs(wXb4fMmUyz+3l;q9t}q^83ZA z;Qg~N?)@tD{)*X(ty{JBE58mzVv#fC;T*AK)juBGL>q_YgIh~U2U17K6oExWM#p@) zq0^>k#ia8qM-*bqb0B2dLlnmUnN2t8ZdXS){?Kk+b%tfBO-K7fDxrCW3dQ z$&8-bz~ipLmNoeA?9;CvdO-w-XV?1OFWLi(qFSB*bwlwB5p)SKC#QN?G>AXuLeyc=TcV&1IoB{5PlVV8J}y{hRMQ)R zaqx>DZb~S^5VWmO&>Xc$WQsu7-Vk8zMdV%8An$TAp^StbNL!fHF_zrPBTy=?~uSPipBtY}Qh8L8y$JuVz1gw8aYS4^@8Xc-zJ;nsfMYzM#l)T~JUa=a2 zZ)XCD*dSG-4TO3nI5VcF^oNId*0iT~1i~qlb*-SC8y| zw1>rHiETb`eG72OmInY+q^{Q2C?7N&Juq53gMpoc;5D)qQ4^AVUx=inF~2!|^7$(| zlI-=l{*>y~Nojj%?Xc4lk*;_e)!ll8n*vig5b}R1^`^Gx;Bt@ny`XgVCQig@`9U+l zD531XWpl!w>A+|=q&WZ1wrXKF8?aO4d!r%ya*yfc`KAVI zAv0DeGs7>pj_DRN+KDmD;|{Kndsg}cq1a+qgl7iM=*Yn8EpXWoaU{Kx1lP-X3K%)Y zc`s(iqUo^xziyE0zxq;OkVBMGWR~cdq57@0AdmS^%t6VU;;3bYvpzvUEh(uKEGV%! z5P&6f`h_fY9d~UaD(kPQjoL2C(FvhTiKs`{?`8H@tf2!T3Nwr7wZ{S=rmkO+f>CjF z1KoEKh^6UAz)C33 zawq}u=N*GgTZr?KV*{L2cq_VQR(J__nmmBJfiR{RF#IAK{5W~t4N+hl%>xqm@%}?Xt?$9h%_{6}j(%Ja^7*aH(9Gdnm5RZ}B=PxGsZ*&GU)u^^^L{5}3!H zpEuLeeSWvqgWN&(v7!SNu-UAF#0iRj0>4yVFET*0)k4NPb^Wu|(5-2nkpgqT;{UUV z`Ip~>j!nM-%yGnjw#LV^pC9=SryPp2wVKCqjwzMy>YGmD zw7_gQs&;KjL8;~gds^RFBR#sXvI8IQuJ1(H{!!|~SFub%OlsqN5QMujGLD~2rOs~N z&MEql@!0QhAdcGgcM3R4<%Kk=t{PcfPkBdj=`}F|3`QdZc-5`(q(=tmosGp5iMn0m zrPFdcbC`k4JhT!0`lk%zjTL55UoP88d31=!&7>#DP6>yQ}>-_p`90DsjIl7$1= zAyTcU@HZ|aeeA{$YLh_7)Yqii-eo%Yyk z=v|mD#uD#F)j@Y#bH5gzdN+dhiJd#XE&m7<-cc4MzE z`)GGJ=99qR(ln$-JiWyU#w5IOB_EeX!GtCj4GrYfVg2N(dsKKxmv?drkU2q9tZpk1 z-M9e^rjfSGg7v1=nNTxH8Abbm98{p~t=p;9itg5d%OnWnL-IQI`y3c~Wc&hAN@gsF zf-&&_ga!dKDMg;D7x;)9!Dgq*AZ zAnfprtGA#i@ChP!!O0P@l<@CBxm<3b)HSO{gLEb+05Og*>E@}uyQvBT?=^m_L{L5c zC(ClP1|$QNW?s5~1(4Mboh3SmVI|KxLLF}h6`A~RuqK+Q`0AbnJB&|aV>u_DLM%VY z3`f(l6>sr>vUE6_pI1sg=3=^AYQK6R#GL2ttLRFonqM4CUNoK%QoH!2XKD^H$*P*YcUA-Q7VR9JZ2mVt)#CxK&GSf>ai0Kb3PWWH< z(kAK-P{;VYzap|Em?BW&>DvZxfwtp=V|@tm3RJ+;4Y!8usLj>Ktm%5Y(F_WiYOf!M8FrR?_{UJ;V2D( zO#mrIkv{RSUX4=&lrHWeh&V>k9?FKoTcGIs_f`Rb9p5EMp2ea`=)Ye)C}7NAiFXep z{zzaWHRWrdTrGE{jrL2KOVTq=^7kyEtk`~eNS`(;heh}3MJt?&OCLpyh$ElGlyfVa z!F6(&2__M1^qY6%Kh{Ech2L($R3c4TL zc8rR@U$U6_(Y?j1NW`#tQyq@1+A%$$fc{v*LV z1@o6g&KW99Fv4bq3u{3_;6qnA5**-_!9J0JB+mF)G${CMGlRBy?9u0eh$#qH*7Jea z=&LUMuW@33e5wQA>{@2L>ix>G!SPGw%DJYRR;c;HaI~(#EQdO6u)#_FoKkY>&KNmz z!WW+>LBaa!qggo!+te=g4l|FK23}tdf&}@;Clkq%QgC6PY5W7ezkfPAWtNoUbBI1@ z@qPUt&v9~me7fg$+hCmbH&`XpG?Y+t!sswk-<#GY0n-%Mp!9IDQl1(Tj`{Q@Xj7=+ zZn5e7v+-v?qrwlCjaa$$e*ec);eb%?CBJY=LEE9j{CV(o-b=@zd0ySwNO5g5ll3c& zd!t~PyCM7oy~k8kgHlz{UIu0;qgND-_aF7i2Q`t0 zk-q;1EOt%=fA86*Ld(hvh;YKZ+!Z&hs}rxbH)AM$ZBVi%UR&Wx1u{E4mvK1$RxGl2 zf>J5B4TwPT-R8+7l?xzPGvdE*3Wm|&^U>~VUogC9c zNBr)%rWO6+j3ZAU7bSb6!y}C zHvmlZH6DT(D>>SYl~x>R_RS$L*|P?hfv}6?vV7(5J-dtj%{&2SNNJ@8QxuZ1wg!Zfr#W z2Vawi61H5c$AEpi^4an_r5-l(D7R`VaRaNyL_n^YnXEaPC@AI@`{%#PJt%Q)IRat$ zzOcLl1FK)6_iBD_n9VqHQ(|C-r_)ge^iQutg|g^3-n7 zZqkK=Pt?^qxD^G$J5N(0_tCptpbVgQrDf)4{!JxPK2!_J`6u_ZDiCmE`DNaBduA#u z`^fnU3gW1IMEZzqb^29*C=v{k;&R34Z3CCdxaG(1n_NZ^qGv!2m9G0on*s`xL)pt( z^BZim(D3K7MNL zQ_*4O-5p_Ek9-SQdyi8eTswid2O>)!j>(MSk6dZVCyhe#z>QCgi*U7Uk*EPq`1)J% zEA)?PsNA!!y4-s<&r5t8VS`>BzY1l}*t#-4w@)pr7M$1a0x=XgoRzG+KW29&b1$ zaIJJj$6>Yg{MR?8f+dWZb2+Lx)$qe_yC}i~r!chwmeGHXMqmO~^MDPu8T`!#%O?6a zxXoW8gWw>os2rXrrLHgqdytzEY(cXJjB)1O;+(?(12kIe{)=byj|LfVwN;oD$t%GJ zuMR$d)kgor@(F}TtI#tG&hh8EOMsGcfSHCi4oaScobT76kd=@cQbJ&K#O?D?_C14C ze`s#98I)Q=oW*D=RjBZYC+GoZ)&4etnT_o8U1oj`D{14Pa|E#Y0wUGVGMfD)!^Iy>fsl9DA(jZ^e4 zT+2`#zV=x_-9OHjLv(vdHSr+{mI>*3t|e@(P9;UrkT9Vm6{3z%QBlDG9sT|1O90Ic zk?8roKOq!_RKo2<*%B~;^Y*>^JFC%)srKlcg3F1L zx8e7XovvproB8N|F;(cryINm?;&@m4%~32PwL!&urgyv%=yvW^$Y9T5HA4v%qN@r7 zDaX)ol!KtcCLpe2V1c1$+;NRwlAl(HU{T#e@F4!|{!E#QGkBA(!@i$yYy0VSs)Ud) z;xxzQ&&v6F^u#zGr7r$WH)M}ypP*d0YW`d~Tgs2Yx$kA7`lphWJzS|frwYcemwq8M zZ>3?$O!iXnx0&KGJ8r#vZtD)|d|(9Y(Rcl5#c${<1TJS33$;gFb*G&%14t4PRXwB0o{K?D3+TF9BVaM!ss+eE`Uc@ywnDBr$Fc$as*<< z<+MKddT5@KmvE0d>=f~Y5%YLi!x=eRQgF0bh49c)FyFH)D&r6HD0S_QD?Ynf*Auto zbfpLsrfE7e9*oFH2e%Tt8`YTKmiVxm`XLqG@#ZV(cfF$D38_Wl=&zbqSvQ{EcqP62 zst8j9%wnbhWRY4bEY6thBrwBSg`XcZhfa>=A+&&D#YAq2x-s2!#83~Rm?>9HhftH9 z^Wu=ttY=C(j%jo1meh||T^Y`R&VE1YjrW`&LZ9;t zb)X=Jla7dWA&MyB8roTR&~B3h9u)Doa3tq)E;V}_kb|!PW);`dsB-@@;z@fd4n)^I z6qT`7L(mPpP{y1O@Uvi>@&4t-@D$gNN3%p(Rv<}!ygk)(MI@|?#}{w0N~eN(T-@}i zX|U-LWU_E8kMFfX+paY7An8d`31Fl86mIwG)l+!H##!^H-5fU=7<_aG&|LWBRtaB% z|4v%v`6tYQ-=lX-lfk;mH69H?bobEze%y9=uiRFY5`EB-#80pgMPi}@7lZo}Z~s_1 z3c>~z$@dG~Gnu7W@H8)W2yHPqf~!dqPxJ?-sPfu!s#c5MCpf)KS58O;oy-_nmv18 zOpVWeJ&QKAX0ptTo_+H6!Zt-R72bx$_c~UZKT}Q=ZB_y3XTDL0Qs;3NU$?;hcgh%% zBD6sRr3v2VyrTE~iLdC*bN&RXk00_WyW}XuPkRrUe0k$kg!?c+MEcR)r$U{FG+zIy zoZGQaVQ4WD@AyJd+7}JI14`HH>>XBRi9+{8e@X0Z{}%mirfn%eRI-UGL;vu5l-iAv z%3`ujsnAoV>6IBoeaGK&6jmp%5@vqHk3Pd+$YYd)Kdqa3SL90@o>{rf=@UNkFL~w6uX3S zTow_hRrUd1PAuEe>qP;aja^T88&`O9wk)Ku{l^3dPZVW8EIz!Qve=iGWOAoiZ?D7q zE`7BmnGn1ihAQaK1e<~;;=|Y5pRnF!4M2VwIFfGvo-^g3G76e(u;jmVgXF`LJfjd@ z?t<_$*WbT5e}s%RHMOlf`sQ-~t!e3R@HZ$VXVZU?(vpy)r-$Or$9{G*8hATIYFbuCWUcP`_PS-+GVr16DWxI0dpi z5R6xxB^^yabPbVnTbWbh{ow>JEgPFL(VCo-9inr5>#R#UrLDv#FWM)@e4r=^6^}-` za1Ntq$^{@Gvr8(os`gB@_L=F)fnB+^ZH2AWIVtJ}X60#(`I678&DkO?Jf2><5YY;2 z?kt{#qw#PDgrATTJ?|{=85S%hp8LcBSJeYO0-STcq)Y`!GXfJf@fFcZDLmC>=rAMC zB2CNYH2qIj;)Lwhd{Qeo@d8$-x?}((yj|blPlHC-h8vAU)oXoRMD%!4L0WK~2RSMe z99{B4H%s7ErbjTN#;BF4p`2h19JaH@!u)KQ$vj^rs~p`}Q&hM0q+6aO_HN64c4|`2 zrLsy0a3XQ4H&n`!XiONdFJU_owEGQ27l!O{KS*s1hDqbp_I<^T%-*<*!;v?6o$RAU zbhZLj#(zyR@YvWz90cGAOC$jAUNUpg%%*vE5P;`!QzvM7iS^B7_5BD>w&~#>$X)>0 z+wP*zueqDvW~Y09M_Bz~oG6$z5h%1M&_XX+G&80WwQ#g>X%JtYmwHS$Jy17j&!oCK zUD6S2{c7?9ZYt;X(9fP1UC1*X?r!BMXr6y+LeX4_qew$S4lnut5pvVeJ=s7-N6GSG z6}*1GaRV9Sm(`=EoFs5GZVu8~KTf-loOR0$uThTu>B@`5)WpvCVVaZ2$mFpkn#9`; zJ?z;6SwvE`kKR(A!eq7bOo#Az6;PdN89z_N^~g)Oeufsa@Vn4zGzUjVwUqk9DCFQc zkKB;Ai5L%8CnnJyq6;q5a@O6HDILh<#O96#87MVAjeo`H^X@(imtj2mnB+yIyPF8< zxI`cIAVh%Re;%G*hfzq2^B5VQAYrJ%C`6FR5IvkfN=Y)Dj}iTwD~lW%Fj9A0cxlrQyPlE?<2`j}Z@g+K6KC1rMjm0%i-y^o?ywVs>Sqj?|-k2`6 z@BQTdBTPZwrbTj*R+tIXZI7l+AL8~s6-X(e7ijpvHc7PJuz)ZUKrny+3aF(=p(hDWC8vX>&2ltQ?1trvfDxLdAJuxg{c5>-?es336n5=*g z*!%VGb`RhqS3sTcGal4~lv>*ZIaF~#mCP#N@J4&fK5|G7dQm1u%C z1S!4C&|>tHMMxX*#d1`p=&CGCy$o(}G=uj1$yPAD=vp=Gu&pX>6eYezI3E2zWvWR$ zXPs-P;ws!;HyTJHNsg%dFKtcDSunK3(-^%e#!nx;C|g_Bijw_%qSZPjew&qBeGb-( zM-P{2MN}w36sCfc*ZlsnZrv=Ib#U>@e8gf4H&ZTKG)t0P=ubm=8%o9}j1a4wV@LII zP(W)lnuhvlaUAPn7@|w}rKiH`ev?n-!l&B(y_e6)9-RWnJ$G%USLjymc`1PR7m_$qUk{Z#l3I@5*^dNJW!qH>}i;DtlYnv3-T$|##e0EiRk zPj$wPAzP?q9DhTHg?tLV)pF^;i-OC!*kD2gdd&<+bTXRkMR?4lUu00w;Z|_SeZQ)7 z>{b9^7q5Sd`Hv^+>Vfhz2dEgO>TdaeHtPQLvna29(wr!TjjKq@54I2~H?B8gP9%iG zUANAGWJVn6C9yYdU+J+ps{Y^LWZ%5vH+sQtX_Wpz$N!BIH_7GkE|J7gusMr}C7F4t z4M!Btk&{KF=3UU#X-q=lW@=6uSyt>S7lF>XLLYxjbr4>57Q^GWlprah99n%pR9?pa z_8e16PaFjj>tGraO$IT=|9j=K`m^2f0N_3q@71w`e~8tRFW&m zrqckQ`6_U6^6b`TIR|E0;BH(6=%@FaDueX#Q=yNFskrbjKH1}Dnr3^nBS;8^8pI#{ ztOIDI-E7;|*-x8f5kb0&k~b}|ux=BMUF5XsQN)*!OSs(Z8?=|^m$XwqC#=5y*z~#b zD3ng0vLmR-DB{tmWa!z+rXrs}YE=$yXt5{_&muZMjW%w~-*+88=w1vy&Acu{$0jx( z|Ae`hC8?TOa5+}2koX!Cyd2GJLuk*h9C7kd{+AcPj}%QTPA&_^A@AWCOThk)3ojAh zyEcTgHu3&oE1ofUuI68>67WQ}3PG1dKPz*Gw2>ZZ1E9o&fpnl$MK2dVuJ4B~eC*M_ zHN~R)j8$!)>`w=o%^~(|R$Eq6YPe)?ojP@qJ-apIMwpl>m*?lg9H2}ODom}Rm@zfm z`MXtcX-L@McnQWk@qkAJZR2gw<}WDJ&HAktGS@D>FG6;dct??Vw1gC6=JKH|77F_-C5P8Y=rpl`>JqdqZ9k5$ znT~n$^w|m5%Zr6x5Q|6agLLNfA*fbqpO=Hn1f2bko%t?)gfQ9%ka`6+Mcr_tgj87< zy!<^UthmPmkJq)9wN4YPohqFO)` z;+Z;l$K|uM%+~Yhy(Ik@rX!3(I`{?WDJUWzJzxlNl92b=^cXnlhsz>Lx`PsFP<|Kq zP8ptOj6Suqi|*#lQdfAy{{?M?b``Kk0!olZ8HW^Kt#A)gbj2%7vNl|%J6NlC^dUsf z@tP)LatE>XzFUCUQ6<*w`bFC{Vt26~_3T<4*6f08t?@g(jkI{>WeFQpth7#E0z zI2RL(2Cji-;)8wv)RzBKmuiVYE7}+Ew=Et#+-Mt!amC`ER5o+ro$-%UorX{^-s#Qt zVniIU{#usJ$!38;gQzu7ER#AR1+a~5-A#Bm_5;Tv@*!K6P{DMy@GX=eisRhU;#j6Q zMCQZ>8^7l3{_Oj6G`_GutDb<34g=PaBO^dHKbwzsj~+DnOs+5zX#p@}6#UGnK2pgd zf2yt27|XH{HHwt~2arJIw`8k(+UZjVEP}AxcuYah zAL*T64m;oTO^bM~-}rQo2~BmTTUT5cq^?l|d&cr&sti9`SI8?wh)9~^&I&M($*;FP zd4i0BHl+@}J}EwlMDRDllYifef5ElJnjbPn`sH!bU<`mrcdBB>v3RH@R%m0U#G$l| z%LS*Y(i>wMoRc)M?zLNvk7chuM6imL-(RoK>G*)Bnmd?RsR(%lwhN?CgqskzQKd~V&+VDI` zX`)0gf+YL^UvNs#Q^s)K&VF0DtFj={`sTF$SZJQ!1Zt%NUj%u$>jsdPZWRre&gsHG z^4q+;f=uilpZ}O_I1mh-E<5fd0#`jKpjx0{Ka!z2M5h|U(Ok@5$Q>MpY~+myO8X@& z{;l^f#QAeG^j03?fl}85hWzoLo}%4`$`V_-0t{@)lMo}ibM{4kGs0k}i93GY9TPd# z`k`ZK9>HWdEubAt2Rp;DFJ}?}0Fp;gnV*j3+5fAF#Q`AW{yzYj&79Ze?hY(Qew27c zpLtw?i;P_|F3{#Dc6st5N0&4~LFhN`-Yy|JchlY{m-4)mn)Ld^vv^e$Vo0^q{8*nP5-HF3AQc5f z7El-YlTVb)QcRdra7EN^&*B>o+4;7zSQ-5&nf3FBL3OU2R{!R<#eMu1^ul-b-J;U- z$T;8Qa%&7#_uf?oXPHiae^aS0NqS}@UTxoOT3&h4mKx6}af3tx;4h){8`-BWrrWCS zF{Vqn==%2319Yw{T$}2nrA$*KGel?OMgQJT_nUe=n(}Wcha$e}#fF$AAvT=0H}-e8 zN^S(dSiFIF+iJ5|KY!{G+MaCVGY81SWcvws%yBj7IgyJ$_4Cpx7vCpTWSe8CtsDJ! zO9Htz8Acs*)cA{zAL@66UA+Vi;d;KJe6gDdmPg@G2@N?p=OQHd;*J%Bf-5KLChdf*X~KijH!U0Y(p=tx(*#J8~m{R{qr#|6q5<_$ie%)~t2PxHais=9W{B@1L9WEYsF&_c0&$0tn z{M0NbPrdemWik$c@LPDqM}j5G!+6#0w&~-9R27ot#{Bj#b7$FtrrbNO8m%Aicla$f zQ39M#X@8b4GrwIr?9qU|p?wrD>Wq}@tk3q8Tbh2Ub$inZ!TK{-ehJB)t}D;mjmwH)xBErn%*R5~7g6`EiH zj0J?Q2z4(%awq+mYr-ixIXsMJ#-J~9;cZ^DqUy#nBhW!G7qCV! zf2s+gmwr)OQGRfa_mSTCKS6~I%K?ZP2K^Jr$V0&H{^>*RT`;H0m)M5gQtjfE-{{S( zykYBS#~~VJ9>@n(?th@H)Ptoz&lY%!9%A51n_cHz^)@4v)tYnJyuDiK9(JD}P<|Q4 z%x(tvm&%wlm;waBe+%FZ;P>fA3#(sC*6frE_$-EW$BNHcHDaJ(+j1^e26!SbUz)`&U(SXz6EckPI>IpTz}zuBtR5^PZAJ%^d;es-7YqCr<>`%LM( zaEM^RG7}1JrXXT=)2O$AGw#pxkZOZ6Hud%dNl~ar#Bv1uf;k!ydp0bX$Y%BoT%pt? z_V1+^C*;GxA6Wx*glzf{tmi;nDhsXOuu^@x%M>j|BgHL61I!+B9i_&M#G1nk6iP=I z?O_5Jn3@A@?R$(Fx`;pqr}VYWQ_7dO5M^5%IR7N7HRe7Z>?7L2b(!BxzOjjbDR{zs zu|MyUuEfc#0+sJxz2~K4p6>dbP`J&(fN=w_kj|!_r#J{xI0;Cb7k1R}6(xT2sx7~- z|0`oZ!VtU#2mP{Xi(}3)vdteSn5YuC@CFpF*#44M=Xm`Lc(*7OyBkrE#GyyI&Q>nI z)?r~L>ul#C3Q4 zGOQPegPunpq%t);fEvn}n)#8;`l~P+7%hqR2_LzU`F|zfPq33FhU3?%Q^RPwpgikeWN2x~;{zqM0_y^Z+*jgv)Q zl+?&=1-P+=qnY41Zxrw;^9)JWVbxWj%>5k5M~iY&(Kcqn%15>arQd`0WR0i7Nf7h$ z`$NqB4xOf*mYv9`?^)=7K{(K&&)dV7z7d!=JLjwlYV7E4f{{PQr=e~iL@`O=VctS% zJ)fNtMm|mgl>m!y1wr$ef)?n>ur4t76(88U0sL$K4|A|N-n*#Yik{+JJv~N6{`V!n z4QuzPZS4G~tY>|g^oU6qP}y#yB{o;Ens;3e+qd2q_hk+yic>DF@G{}T*Y-GTWmfl{!{L?pCP zC<7`kzItaEdHo*+7rRfG&#p|+wwJEUSh~)E2rRP25Vj1D!ye98eFXE~Y0kR+?W>6J zmGsa^t+SIC9p>Y4Xu0+L2tOQiw(O@rb7p~lM_Nb-b%f^txsSBI_R8}OOch&1w#=Hk-nHy_933V4xGt zo_!|4Q}Yx>PLJX@T5*T5TknouRMS|VfZ^Zjl9DLwo@N|9i9kR$=9Hhd`4B~ZXbUm? zCfSVYj*H5o@KRUegW1D9AFUghm*!#wMdZ@1IEYqH_489ATBniKbRfk)`?KYKjz$C( z<@LMG^5KWSz4dz~W>%~YZKirWH)V3i1swx3vUoIu(8IL2sk4S}ZY>tpkk^353PB_d zE-3AJDOgkDRgJJjYP+L{nm$KZb3Vnf1}vFHl(b&au}fI#F+1m$X%OC;pUwBGh0KP% z5k(O`95{FWOBL2Wv{&-Yp8XuBXn{pV54$IP%a+2+IeMPyE5pX52h-KjyrKUWeB$5N zAk*#^u()i#R)h8ZgM2hzFL7ImI9;a_^mDYPFkO9(w3Os6aAs*+IF)>8uUUP_P&2IE zUBUC5r+WRd7z-onmL8aFtG~3~IolAq1ExJ9AphLJ+bm5W_{l_lFP92ti{>ss8Wg0O zy)O`~SRAn8>$c+RPfy>^BHBZ?nXK%F`JDxD`2U90Ni~TT^P;p4qLgnScDz1El{u+c zIL>y77mJ;NM($G)+YIT*i3Oz4gq0poHo@WiMSYB%=v7w_sF*F!KV|XS>orueF2+(` z>?h}j_EDM@cvt3pgdsgFj#3uPhCF>C>d%~MAT}v1D_zA~g|YpXsO0aF_t_1Q z`L%!R=cI>vkA7EEWmRo{XeR4wB2~|c#*y+JqTmI%EmMH&@HiS zKTXR=-%Axr)=I)JWM<)(uR)yd`+(k4ED37hcWcdbGr1)JVrUu zRAhsd89&M(DJbWco~4tYfh%Q+@B)e`DPRlmhyC~Y4}cLwo{RvJRCIw|aidJv{rtH<1 zDU;b4Fe1F;T0^MNM_)v{|6LW>JgtaMi``-bsLvLrp_WD0Ciib)IK~ z8z&Z-;jjLPbcQ1caw0aE+=Z=X1NG{kvUPz%#s+Zk)of0>gVJ^4qbQ8`pfPcJZ$%%4 z6bpISzNa|Zt8G_h0Fq9Aeyr%`YpBzSHHn{;_Ktb`zcdQ5ME-zt_9_-Fz(jSUQ7f`k zmUJ-R`b2!InV7j8lA8>St&gb}W zE8wtO^7>d^Xw#FZG>HZ2vBxOKSs|gjz5$vKz;A}RZ|E!SenvH-?7b9^jLyJV;LauS z%TIA%p+&j3{iqXRTC}{kQ9>YIA~|<>zdp7sZVvjxXmI?+XyqyqI?P*9-^ZQ$HI z0Hf0MyX|alObizHyvvL8{R0jRaE5D?N;EXqn@bT0=m!?0s|3@Kt>`11u@wa$d~^WDF1W#+t-*s z21VaAd5kI+L#sj8LQA-^W9(nNYoIMKN3E1}z1sGw!d7rxFw>^{l ze#R;FB=_4tp(_^aXHKz*C*bWmvGWb~Of6hVY@x8oNnd-S1OT3;kS4}db=W*gMv~RM zWLA#VT#6**RrM!*UV>F}E-@?;f^>&S9u+;Rd;}wpBlS3wf78^k`+7*as3B8bRm5Bc z#xQ5JV%&eV)}Xa~%RTOQ;|`SXStS|HT@rpb^j&HqE~F`<;?druP#{22TUKkTYPH)) z9ixI#+2DXgt6~_wB=XyAJ>t0S>Mj%m3d-YVT=?nc?%VQf3j?P4m^>6>>AGUJ{_OT0 zlERDCo(?l3b#?RK$}hb*pN6SF5%yhiG7DZC*Epn_PjO3=KgA%FPCVF!9@_J?yTInR z*FLOZ*?ao$i1T^JP5P(=giMh&M2P)uno8#*<0KLBp##9lj#xGjy0~5a_*;fWDe^;y z%tv|6VOZotg+Ib=1lB7#AZ93qVjn*LlC?eBFr_ab(8sD~Ly7;*7*VA$b~>~;Kb@Z9 z3~N~^`09ibxsQ^&Lm`)y1UvWu|E77!2jlgE%Q}W-v?&$QBIQ4}fo$WUDLRB2`;sMa z4Hwrx1W{Sf3di#21Hapl=qrnx1s_>?XJwEX?)VWz!{RPA-1 z`;*3I0-kNWciZmE4GRO(*#ARhs&}}={;olqB3jTe-C$Afg1mAU1%mF44#v-vpolzt z85>)epgj%A$pl^(*8>bk*3_1smt+F}dBGA1Z%O@CfZcEVM)- zH0TVe3C55Ayz4)LE+CWbnq;5ww8%fe4w#EfJMm2C{)3s`+#NaLgyRQ6fabXqQTdpY zB&RW-?Ej(dJ;1U4-}dnmS%nZuRzmj5UPYUdxa~cY6|%C*jzYGq5Hhm&rtD4j-g{(k zzw52f=Xt*CdH%oS_#OY_P)Bs*zTfxjeU0-v&+}@u$1S@ZCh87*fgV4Z7I{(IOg3Qe zZ+IY{j&FuCh)jo0bFF+^8CB0BwMr5F;LY|Nqe^gSE-+@oc-eRNXJayeI)u-^+sq8j zX#DT?#3$s*HpU`K5Gx(^f91C`_ol*H=}MjM+KbsQI^x9Zv|gY5eS3XqpKnCwivLVc ztTdpMI6Ls3_%s3Ab|1FJW~OZJRUh1eDt&s$vMm_KGNB|v*WPsp&`Iioj2T(|vj;6S z;R1&%dgmP|-l1v)$DBalg8Eb=>y;rTTut?ugJOq03}6$84EeAXKU6?Cwnr%>4tC3e zc?mFIR@Oa$sWquEzStR9ZDq|uJO(4UDTT7Jrb`2OE;Me4YS*6sEs^azB3qz%@PhzN zC-w|LRypE8{dB&+eKnVM=~k&9d}YHtq}o>#TItJwQ$HK85qf<<@?7i`@Xnlu(k`_5 zMg${=9uUtxfOMiM5a{#tAIhEb*lm9Kk8Q2t=E#wd1jfYPJs>kWO&_)(0A4>Z%pc;W zftBpULd^mgR0JYR;9E+~Dvo-Nt^*a#3*mZ+CT237>FT`LQ3UnFy|*OpYVL4D#5gYt zS_NgM5V@nyeuCeI5ODt2WKDup_l=MK&~YN=?4F`sLMB`rHY`D;wG{;8!MKypXE%i( zy!@3GTXx;H}n>QMDA0XHnY3aoloq3&ond>{JkOc}d0Hr85GK%{BHSK`+>>=`=ku>14Lz2bWinNrwdHZt6MNZ8ErcbyqO#65h zs9$u|uytt^f5e}sJ1mt((ZM~;Z2vVtI~0V#lar~C%J?R>;T`nM74Wru6V%PhH&7Vi z=7+pEp3kJ!*&Qm~PbpiYDW}1G=8{we zDaP+HWL>cSnfK#qh)n$b`J=6$SKY(^&>`IgtZjSAuEXf;h!4sZK2D@U zUx8VS>YMq5Z0#BxgG+6XsELsvzt-nBZ8E**-Vkv+6tG9jndVRID zV3dGCnc6B}5od+VX9on1CP-4v?5!j>#>5d+3HZQe8?A$EJYjkaXZ*zT7Jpp=>fdua z5}3SkOicJ#xp%Y)PpW-Nc%!Q2pap-BTywCb57cgkCScbhq2}9bMmH2HMLw93DQyj) zQMBBfLretn7x{No`|~W5AU2)wzs+1&(r=lH=fPqGuAASLWh?|%$)%mJvyG|}g#z*3 z&2r?9foU)Py{LPqojRJlzW?plNJ~yGMAER))`jcF*l!7H8)YVzK^Rj2AI@X#Di55V z`v8nSK5EOfyQ5I2ugA`_T|QWhN=!wNkTDnBv8d=n(dnxZk94 zX<;HY;aDAXYctIMAH!6~Jl?;<`M(ZR-!r6V`YL19B^m&(lmHtF&Gq>AU|g#Q-8UDk zp@!rvP1qQI2Tcnb;1JI`pfEiCQVFUJ$Y%=i6DttifAJB<0gXkEZ^|V+MuiL8fv>CR_7K=pbkBCWx{&xM zYac&Q6b|hyb2lo{1Wu7yxf}%vw0Ge=)5~sW?kztIFMN zm{^vI?UG!)a3bCippd=uBc!^F*lyGa#T7b2ta3KBU>JEB!<~S|dI@g7NjK%Ji!ztB zEn1C17F=KBhH8{(eP9Gt=p-QTRI!~vetE2fE+Du^jPPPLpk5Z2bhEz8@l>95;1UV; ziNe68;}1(bKtqDY#G0Pp_YaE@6&-ln4UQiG(;w}ltC?hTYa)X49=oAN!+F`~_MrjE zhgv|Uokhy5T)#yb=94|&M*)P#k?y8?^Nvuy3Jh@qNtPj+61goSzQ)Zu-EU4qnbXlE z#IK8RYF*rMaiTr3-#)&K@FKbT;)M|=CXIqBG$em<0s&A)ln&b@nJ5SqPrvShOeXPX z>WmG@cUIaE-Y(~=9C+(L{D#gRj+o$*YB4_iSO)pQkRz!c-2k}!(8?wtyF zD4ypmwi_y!R`^oQmdhp^iteWb!dv<7 zXsWT*XSpyK-mV4q-Sn(WQ2=C@zcAqQ4?s4mBsD&*BhB*}rw)w@brFh2QxS=?=P{FB zQX04;oKafSZ>o>%!d!PqPG`~|q=90>ouk|?pY<@T;+b{mV#(JoI z2VkR%8IG2h;nj4N+F2^B%B`_@UzE1Rm`OBX6rxNBg}Pbaq3Hi*910`tPY6BH8n}_? zzm24&0sK+Eo&vSj{by$Kyrwsp71D^|_UfB&X&ixi8H#azm`eiKl;AD+RZ->=0F1D3 zEu|btyoxs=*84NVHX`$BjOL>R)XK$%AjhSZa(K@fDZ) zEZmU9>oYEZCw5gaUfcqhl~nluURmG>O)SL1PygqL_7ehuPIqAzu%5m16;?-FKE}fY z;NIWtK1Lao&Skt;HI0{*RZrW=vc#*FW!-(QVXG*fZ9uCoQ1HsxRVIJMxQfME3n)z% zTyZ=oVE5aQ0yf!M)$z{Fnl=K2Q%cB5{kA=dfQ99EH}WHD}1bZT0HsU{ZVmikDXOx_`uGfPStF6GNT4 z`$%4pTNNdc?+ys1N!wp3sVPZ;xw^`mv~1drI)oSYM;NhABJb{asGw#QjQ5cuUu5vp+b9TqJf62+(bpUj>JKYf>L;1WX1_Levsef@9r1H~S;ev0!jg^gE}x15KYD(`J| z%ClXNkHCHU^Pj0m8usAg2(rYr!d%EiwElIBkd~aPbh=?r3RxDsX;=#4dIL<@577)D z+kRk*y>1eWe&aqFWLkj9D_QMg#tk@Xec)tUDcRSPb*;@^OyK{nG`GM9;+^2pE_+-d4%B+DY@-1X{2BNROUNbm3{fUB$t9fe zzioO6iUnMoQbwIx--hq4!S6;k=Z7C;nr}8Xv8QGlBYdTLZ$9RTn`Wpc$Ybb{DY)#0 zWe1xb>YeIN(|SL8(nKBlUfp?-m8DZV*RFko5V=1#Q-J`O{eM#>_TQ#NRJe# zyuo_B9$L{Z`;?HknU?|D7-d??BANxVKlF{TF}}O9wUAAyRXlB7@LHG)8H_WOPNLbrf8P)_3~XTh~2rM`pgn zMxft*)8Uc^8Hkxik9XH=LRg);amx>Z{oQo|S!e5FFpl}9Rp!AX8@i!EG(S`Zun6l? z?R;h|78sKn0}>>4TNZebZ*lNnN4%j>;ky%eDJIg#-r1hHUH^0Ad=!I_&B`yz@;~FG z>0h#6?`@D|ziD}?1TWV{3XaCVv*uMrKwZob_6HDsJ}rQK_aPAD_tovvo{y+NjNX({ zcLgFNBl{1XZX1;rP!BHCe1~HQs2zlRvof-zqi_<~F`yCe*JOyLu%^f*0WSlmrLi zIh;t7p29OmAiX|}g}-1J6>YJQ3?BKa*r`FYO>~gx=0NI4ORVu!=z6qgFWE8{yWo4h zOju{}_^(v=UNu|-?GtkU_ylDx6wLynfH7FW?uN?K9k_*sw9;-GM06=&iu|5Mqg?d} zB83|TqOL;zz$5~f-7WL9J9-{l6XrrR*AB0La_ZxrS$*-=qAR31!!ugJ69ww#5gEuF z>+PPmozLE56*_*tRC>^>{8gKtik{!U%Ghl-0-`!|DNK5Qy1(|}Dvekq5BV*HliIj@ zPIm{_1yM4+9=f``mq2YQ=pL~&^1VcJ@@0=vhGCmHqiPEEXLalT)h$Qx*a^fiuSg!c zAslP9IHG1RZg0|Klnf6TsFuJ(ry#JXJgpni+7>mkc4U#YFk(2 z$*MHm9TgR>yYuDDJ6hp-=vskG0vH6Gv`07g1eU#~jE5d;K2U`_%JjvJZbaRun#C1} z9!CSkC`mP9Q&juxpbvbxfT1vfX@&yDt9mM2p>Kvnh*dWV5m|W-LXQJid;(L;pDxYi zwioEnU^0DI5ku=Lpk$X#5K>-MkrL3$|4Z$DS`)b0yMGt=L%m<3Cfq+hSOsp=-N0L( z)hS_{9TH+SrqHCVQZlAc1Xjt5(; z@CI02h0%yl>U<7 z>!mO5DA@fRy0r*bFxE!Zb@D4XZPx&2rG?K>dCe*h^f+el*8o%PB(Q5Zv;Ry=YcWrG z2|RDVch0nj{N0eND$&G%K27cgOhuS-8CnlmeE<^VvVZyi#IkK}kwF8xMmrT2L*y$L zWVI=;>Cnv>r~PDvYYP^vA(mx;Yv(O-DAY~Gp% z)T48D_h|)aSf*jcX)u^5NkG$0kQ%yt4vO-*!tQk_!S_UcDc2NH1?i={mWjr|7}QWl zY}{W*0ky5Vz%*9j8?GPfrJ8foObb^aWvYXxgrsfS%f4qJrCTAOH-(40VnRHn;W|s1 zYRyIbg_Of~`)Znq{LvR%X!S^$gLr^e62hvtl>%Mep=Pqhf0TQq#3nWVn|nYtg_zz# zD-^cWh;rh>6^_chQOK9UMj2)D@{H#gLZ5?*R>Cgr%}T%Of^ztruUz>1K(d_uXCAB@mAm#IeKpu0<}bu3XxJ>{?!r;HvavA zV;nSvnvlUJO)1n+bQ{PK-Fl{|tHgoPOtFCmGJW`$n%BFu#tDqzv&{3l* z47=#TMYlkmpfz|!1q?=+h{tl;L?f7onYfSUdNaUQ3FV1)nBTl9L@M|ukr1U6duCL2 zf(dkqFS`Y$_JiHfA_ZX=6T*X4e=U=Rh!CK`?D#=nXI@9afQ9&ZkO^U>ragPRF#}kK zIDR$L9}e9A2-|-Ls>Hw2S6<-_tHV`%s?`mv5HRc%btFTORZ85!nDG|VjWsFYp|Iv~ z)(=&2v>l=9xYdn}>J-b2si386%jk*L$R3VSb#}HTPO+C$J1PaXQRL!q%bSzqHBaqT zGil*ZLfX}75|29H#s4aF=`Cw{sai#Q6~U+L4Q*daOw-J={?Q(^$&N~R-URk7!-r6W zOe;X00-w#|i)uLa?YTP@t?T%}u#C8a{83_P_z>smi z4u8SigMUK`fU1?vt23PW%X(;;$1-e-4vXbQgs|`cY%kzU8A5 z+$>@@xourid72Y1T3>%y`BD!h&~kUS6X*;3Y5yNjEZ(JWaD%g)pMx}4xJN{0)w1BSeT7DD)99GI3yv)Dx#E&uVNgi3vTtc2cQ)Xn=y zav^~Ao4E|pQ3oI2JZXNSh=IQbJa3D#J8m>ci~bANwWklUrKJFuH_~?EeepH1l}5U@ z8sJ}KnWyIM927>3Jwkg&DPmtQ^MC?{D1t-WEcAa8?f#f{ZYPue;BdYCtpPT=Z;E{o z=uh>UNWukNDN_m02yiJgNfRaU3ZtA&zpLjB$TZ3_ysMhUCvhtz7o&s_E#PBkO8YF~ zi z6N~t}zP4+!}T{j}=#q>yjQS84!EYV$7ct+BIU>V`U@HnRf&5W<)%n@vbwL9^$oH!q^PGm_WKYo8%oblkJ&BCuol(u7M?L$QKdn={_ zB&R+brFZNB2&C8Qfi~swqFP6)elA%&k0QZoOwh9S!sTpOt%!cx_d^pqJE;9FZa@Xp zej~C6p}2hz+oHl-@=G%$>I~oAWuP`JQlb>Vy#rb)5}<63tA!^h z*TY)fwRg7>Mi)@K{xXIFjH?zQ*C3?79B~8;ka(B#85k%LJgpl8$;kT1;MsFGs7&!` zuBO#Qkpl)*LTxibO7hlMc>Q6O+l$`xs2qNyS)ivRG}adApzk+qsx z_8GECzRk~~eW&7Zs5r}RB~N%>mS;V6g_4`TV)A5pu{7MM=%?O#W4ZcF@TX}JIxB(Eyg~k-Bv0t zT`%C2RqvAGgh;fLdu9UKE1$ja12QVw?f8G>m-m5w*nzs=TkC=rMRavIil8KAY76qm1A^rn>>$WuO7G*z9<)i17s~azURQYg0(5&VZFY)~(dN ze6S}9MP=tf13JqMPKArgaQmDCKy`bYUO6KIdeX2&d68(}xoVEGKxmIpK)Fyx2 zhqXZfwwW#~Pj0&peX06ghb!y^gnRhUix^m`nX%{bEujhfNG62#{LA9wdl74l!9OqWK*8Q3c!W8o}$*J$mu8PIL0^cD&#x)eqiX zPddMI<;5Fn^)IA9BO&bJ8&L8Lb+m0$t`7Hcma@W0)StoAKjM+3_1kDvv_x5`v5 zJX97vPW|rVx)!(rTQ;&+kF%?DBHeG?M*EkKaGF;=t5@yIWnk1P(zKDs(T$PlFdeW| z4xq$+k3AVeFG!ATY5O1ppoN`Ua0=5)}P6;sH*MZk03FH?&_yGeEmw)ae zJmrE=qiUuKtD<|UkAFno-*d2KC8R$4Pai-gHo1E29IZA{tiVZWYry*m>e6=Y;WUCw z_Ul!amr1N68`c%w-N%gG&^A>n&9_5m|K*v(r$vw6!a}yTn%D0b`C|0<-vIY>zi+)U z0bV*$4sPmwSoh>7yzVuY2Nc--C#+R+pn{r)4!zfoKm**noC8$M%24O=DX%HuGpxPD zSe1W>XbM=Ab01O}tc#^L=>_nP`k+62`wt&qSct}o6@GVdBgZ&}#cv;N{^0G|b5r0) zl3G6Kd^kykh=tvRG)ir=DnHJHA5Q|%53r}3|KatoxR?z5?FI1P7v@bp4MftyG%XQ)y>=me3n20hz2kbm zW_tVvn2Q(79{T;mQ~vwu2M|02nR9i@4bAWwZCcIbc7$v!k^}Sf?Ui9> zWXVyMP92U@*#XSW7uVj7-PJ;+`;lz_`}3kEdneb6I2hg!*%OfX;&imnWwjtTOvN|; z3nu4`ZNeKL*kS}M6NfCCSOvOltlj>@^J+vxo>pVE$o+nBLx}s@U_?iYT)l`)oYjxd zoYsWhH=%BSw6{LJ#VM?GN7o&Cx7x~+e|lq2uTmrRpC`lQieJ`Ve8EpHqvE*uc={TN z4KgkOUayZ>RC^KKcmS zwgxwp<{ILkCyuW?4}7cOLDP~J!GyY$E7+3(!^0*_) za@d^SaOKnbbW;=fCVYkJFxzxkkPMtc(k@^EVpFF2y5pYUstYcgKcv9LFra(3}bX_p=FK zsU|{>)uB*mO9@+*thUxWgnyWJO6ha`76-8Gydy#Hx}k8XZQ~QjD(ILsmO}nKL@(ktq({Ajl@@y#%m{Gj|3kq0 zhbQ;{+tc#LN59HzeA97%^AgL45h$-8nI(f&Oec6be4V}t>*!pCk9Q}dty#VOQ-8SfO>o7hK|31^gU<%2InrL5XLwRrhebLc?^#T|XK2i-qhy9rM^K(oZ{tLb zj~-YRn_F?42e4WvTbx;ijZKe`qYLXFGt$({1c?eKMrdD9!CQIbWXJi0w6|wjcdGu= zI>`TuF4s)EYZbuJZW^m{O@QC`W{3iet=2)+IF|(`5p4}%kV3vgIWO8kA~d8BW@o?N zz+mLGwb)C#Hd<_zYCMqp2r;b&vn!=yb2?Qql?~ntLa7^wXH2}W;Nz!)^EZz66q24& z6zz=IbBk_g*R<-6jJ*1B(E>^ll{p6uSS(on;T4O~Mm}&mxU_#_iHsm23Gu!?j&@qk z>(yNuDk@ivPxt?xMXEnSX)|O#p#E|oH+jqwKgMP^I*Q*s&H=>mGV#C5)bsoLg-CMo zUl4f|9hJoix6YL2t^9C{>ZX5D@qK^Z_Tqr&w`JjjGW6wh17l`Bke?nwgFOXJXb@zx z23Y;DHA^A7vxG)?VE=WIf6mfxf0cXDNvd!9bCkibL|8AJ&FWGEB~zUkQvP(f_ms*h zwxiIq?^DkinEo0Kr+3!rAJ-j}Z|bqpRa7S_`O?;(Le*`QZ|hFR(4SxDA{zf~_Ik9{ z74`o7s_Yu(?jo?mz{Kf`g5lR2=?SnT2!IrIpJzHiok7L2!%ZPQElJPF*geXpUtO$; zggr1z@5u!RCpZ!Et)d6U0vpZTTciD9u4ZLhAs}@BkrL9=Yus}0;0Xr2KDRxm%nF5+ zx;qD-agB(!L1bfQA0g+L!$Z1!gg1bh%cxt@q)qZVQZ7wV#^VARFu#z1iA)}0W8OW{ z!!-$@ynk34DH|--ZLLTwMz-*^ifLPOsG)1FjW^-BFkuDxQyW*?Wp6?yCfh178>w3( z=sa9(#idz!rcLlNlbk<;ww}_=6gL2UmpdcJ05}o zn1NoxG*86RD+w)u+hHBBc6%Q2vzM##zgGGs(#^GH7s%&c(!yQy48 zTI(Rh@C8nr_B)tGBdabLxSKnhz(SumwjbbgWU)wKqX?#OgB3m88?NXNz0a+JE-Vn$$Mj zmuLz1WLE5?<0*doNO->4X!XtazjJp_T~7H0a5QBy}^|?U^`%@fsvukh=n7$w9d#gnpp;i{m?!ecXDEu#445RgvW|? z{7+`+I=(x$mu3r^;R{R=RB3xmTcK&|c_nJSRvD^1PdYBz94VzPf zc8h|o40;Kun`me5T^uF7VmZH0C&`wHJLt*L{PDc}+s6Lr0v{5hKr6W^;JpF@1Skz}2cR2)DHQ zL!fcLj#i9}oaLo9feRVN{hIwVaPC|-pj1lh?I9?tiq<@+ia4hA6V`5fy2npCqYdFx zS-NSvulgK5H)&3uQ;3PWRxQaD9fv5GXz>#-{nnHwpq$Da^)k9nlZ_J>a5vaOi_K$M zB8)SfsUXv_=0M-lt<H2ilIjmc{0!k7S}wj1&yK8_`Wv0l@ks-+dT;I1`VmB;cKpDk)! z^jJ$Jb32hJKH45cu#b*9j{7loGh}zLD88nq7e6LpQ~l;A^m^_~8EPEaeEbPnRpIP4 z?l4yQ&Z3UOX6)IRATgEZ{KKM3HWp8WY*}LcdNSatjL*?g_4ZjB+!MrvNAhT|%^7d1 ztns+K$NY-*mDy*5v^1Mk)!Is0CmibIOjkAPAHrgzQN6|>#(n;Ulk66}9U}b^Q9y9f zY(75(_v#92>;Q zIp#3=k*{%W{D=8BXHCx|%tL>Yd=0_pY|S-twsblH>07zReyl@gVMSrzw{na(aJciw zXwFl1_-9hRFDnCY`#H;{iXkWf2U4%y#U=2IdrHg*=eSSQjVv&k3wKbV)Qq>6{`tHO zQ**WmX~zzS<4w5|=4O6Fh(#n0EGGwnao|1bgIw!545O* zA2j?(?5qQUF!)EH@f8rI*Z$nO!Q0YA|6-Hq>DK3fwDlw z?LrESO`79>!JD&{adxRUll<#$jn{NPPDJTV2@Bjkj}~*uF{B;bTPayx3jH|6Ke+UY zNK2q}tr~ZrhKBb|6;4HE#okN=PpA}jDjdw{{Nv3evH9}rUxxq}Nb)N?cI_p=dV{R8 zfJd3V?&es^4EK1#bA#`x_4wtLRgIJV&~)-G=YD;t>#CUvguTWs&uHJeIldgh{>4Cq7a@rzF%veb&vY=4GZKB42mC(sVmsE!qU+2;|b*svvpAyR% ztt?0QO}7(?CVJwpVT%t#Jw7-2?WBoUXh=Ft)J>0)r^2`mxhJTNE8?d}^YLZ+?X>tc zf1h(EqPfH3t>HFca(U{9b?xrm>QSC;yYJkzyX;Grbt(^j?~tYI>>paxv`UP|OF^4? zuRk>V73+aRRo3)!Hp^y|U1bhVA{6?I#Et(csx(jTSz z5ei}E0Z;5%mbkrNvU!XLKOu*dT-|!Fj{(xb*xPfj(b2Hd)_yF#PBd=2H>9GduCCgd zcbdQT*<57vd)l&Fn49}t3iuEGv9ZN&&5eKLmQF=amcbz1=lKf z4Hr$Ko_)H)K@ZkagK^0#4J$S0D{h>YwfdOp@17ZN>z+(M5)6***Y!NO*mTwu1v}7s z`_A)U(Nk8uoR3e?sRqsNzPW^I0SvPoBbUT%16(v;!A!SHU4BgM4Ec#xUsb$vjHu(L z%J^lPo68L=PUQEcirr9fsh@C>dy4kG1N)`jCrAa-EGkvJ>d#e;#h+ zWRfF5+EI{M8ZfLN*xQvYl3(3gWBffv56)FZ%MMB_-cS~;z{eR z^4w)yJMV(-x)|$8836OG#b@&MuAhk_KD45rB`yE3O!=L~Pj1xtq^z>tg8pZKyAA0L z2Y)a+=vAU)oekIZB=_=`;B`Z_ViM%y6EG`9i%|EtCXpGxs@j@>0Y%y{tN1PbgsVI+ zU-V{QiRfE11N+It!;Q92Svez^8CdV#+Z7)o-n-W1um$!|BeCB-szCk9n9|BSOv-i? zNBVE0AgKhY*1^oBC5N%;^Y_VxN3L1-X}P>gd&MjWP%Zi=!(uZ10E!j5lr~`>+;Y#c z?5p!&#`^0zO)AT9hMwNYgr7S@jKlNEN`obECnA;5p$gqiFJH=T($Ew z(*X16k7u<$Tw3`RPS8UVo#wx`K)fip_`oXqk#)oVQZE#Lfn^Fod*RUqrj9#0vpvuy z4-ecACe20Sn<>&I7Ub8v*4tINVC=6(nGELFl#2y)`*DfYTly`mau+xyHMSl*eliql zTXu4pNhq!)-gI0~0F&yy^&56n{qzKz+XwE$g7x$bSJWjQlEfKGq=T^CZa7iiL9O$v#tJI2XL1zp!&&DIk!!? z;S|Oqr%;N%w~Ooa6sjtTHQmbK(7}yX9izEwxHeXWtv=~1vaMKF=W5~BQ#|P_^eQYQ zXufF9n#c(`io+w!-NF^+6Z=JlyqCU?CTE-Hw{5DvE*EQc-LCr1y1w4OVo@?HSBvfR zR@8Ke|A_Xbs*sl~L4l~QAp2>{!gcg>*Gb?Jb-gEM>AgGGf?4iVB8&SdxayTPMV52B zawCMj)Yp6nY_GatGJEOxkLlq!m+}W**2f~cW-k4SAo1MG=Wg@BnTcu5Iq5C2F*{v3 z8|ALRJmg#URM3~Z0q@AqTOvgxQzrAm0H!U!>tivceK=@&-;kx;Sxf}Iw+07^;IedSIBIch1&K<1(cdfo*2R~4$3nib+A?i zyJh7xL-_5Je-2~%bYRxoMT^3y{AxA&R8l=B`u^BanbtuaUxE8$cIeTM2=+t=vgMKH4p65`wfrYVDgG86hbr1#)t-^WtH*v1pD5v=PK zJK2+t!gnH=PFKn~?`bFER!AnSGnSg8{Uw#ZhKCEUg(Z#DO*NciZ^uC30y+BUX4|{H4PqwHWSH<$76AE zHQ)_@JUvpEzTl=s=hwP!MMIBpq6_V^;N8!`1zJDO1D5>uIPX*NtiwldigX`;X)k8{ zPXwLFaOVVCj!kp=W8D42IBm$F14_uoRD1lK+3{U(=Ja-LbOR^BHf|(!=6F8OQ>50t z{?p!S;aA55^%TR#2c5k4`#gb5?K?MTm!bGmI1+fbsNebH+6aC!OUod1c+c&F(qQqf z`7FiBBxy00^XG=3hAj9!*MFMBA|DZH?#%aAsX*@O?;=Co<<6G~uSQ#P2fGN{9E^&| zS5zN5>gVNEe9ms76KZp!O00t_ExcSqDMMNdrR40g z=Wi^LYL9ZLF~SL27CqeeZ-f(8A-4`E%;@xlW&G<2;~iaQE3oG!W7zgD+&0p3UV%!y zM<#G-ujozW>BORFU$;Nw10mM>_&WkQfQ(o3{LxqV4O$}^!NajrD|zf))%s2JHpbmE z`Rv&PX7p(?1htwu6=uaqeA*$n>?v2S8Lv&2i@&Ci-ln&P1M5qr8&2#0@uCajqF#~y zhown(Yw$))SITzO-(4rej?Nyl(}lG&`@%#gdY{$$?2HUP8E0XNqyK#3smLbF7`Va9 zB2?mI^5MuRz3BcLvyekRui1#IJ!WpLXze-ibNbiyAUQIm*!gIfSK|@^C{k++t4lX$ zAJT^@t;&SVu!^sYfWvoIo5CVxS}*W0ngC$j`M}i-nNi4WykoI=F}*8{!|c)u@#IBk z+p1{+;cLptFhfSmx=;U{zMrmyssgJ1=%u5$#j8h?4MU>D4`zx3K<9lvuca-nig zWY)7_o1m;-vnbgy2Ke}maRL{qrPdKk7ho-{X`WhYBwDp;zXi-E?y{P?)!9hOxo2Y& z(PM3scLj5akPff>$iPqj@Tg!%lCCWyqtKe|`xC{Tt6xXuhrg+F!~gG7X6#F5D#dyn6t*C_t@bRv_z7SvytOT@9a_Ggaf{V2GC6#YNrNtNYfUd zxHW%>!$%0lQ-02e@herol4UU}zB~$v)5hc^b(4G8$5F@r88I8uHH!#2{FCwc{KS5y z0@NqQp!tpF*D#IewYby|6hiXs`hAN@8-*+mGc=n_Lvz=UrrDi4XqJ|wmMFikfLmW~ z2}{9=-yYPz3ySvTgppoRHA^8XDM)^OZNgY)RF0c6hTssAb6`F@_7b~u5~uTZ0F+*)RT=nN;SBZ_-`2TB z%!c=u>sr4*AwIG$Nq?kH?8uR|F|<#Th>vB-soxwH_7M#~0qbJGJn>A?;K7T1K94e1 z-zWXk0a3H1q=6ey;Y*D$Q!PAK491uKwBwJ9E+u9;yl=c7MK)uWrkdT&bwokt5jx22 zJt0t{*2@m5FYYQse|BA*?R|PnP8{|A+$t{U4po1S4r2{_xqXyQ8$SjtE6ebl)9zUe zr)OvJf5QyZJNTZXKg6tZ&+%#NwthwFrp-PaAyP}d(_`iPo&L$^xvg5T11P+hr%35! z{K4w?>jbH`dj$t;ixPdD^V{mlGkaUztNY>V5t;jeFDt$;hL!5SVJqHZm7>C_S+SVZ z<9Z5=-`#Q1>y4W$!$SIe)M*@XDBXnzzf5-sZ~dvaTmtmVO6fJ%$3I;_FU6=LKS#)$ zk%he&LXh4e^ksP&NA1ij#8D zwkhXuq;q`3`L1dkG^`66UU$OIhh~L84vz!?^-iA!nCuwcATV4SD&oe&KeqKOVE_7i zvaSi}s1yp(>48$&KSb_wn&Au1Q6t8_l^DXpO)zGCf>8b0?mo&;k)K(nuo=39TeNs6 zTBAJ~#3=g}YCW`_JpwU<1$+-F-?GdN68saOU6F9WoF>7y$XEE#99fynn&{$q&MyY$ zS>iJHPlFguh3MC6;ePx3pJL|i7JCfDtW8bg<_ZR_o~*~sxxSB@?cwVZ1tU#a>h1gd zm^b>uV4*<#aj9jAli)_Ru#JJU%dz8(v8Sc1b*qtXSF7cA&6IFA27Ta8qh~RQ{C>zz ziA({_LCn$|pMEr4>$tX&PKC8=^plot(Z|%A(K&-wN9$Y-%-*Nqg|~q&7is+1w8L@u zUq{XuD0*X_gb&$E*Tk0|^jn+8Kky^L67}z#R}u`gytG5;K{@~%SbP4dzL%>d>Cqiu zrVtx&dw3Q*R-iXci53dB-r4!>D^c@B-^?0+$7oPh`#!20ylb)0+e>X0@G%CPIXYP$Hmu*2-@_c+HS5U#h9drcz*ac6 zE^`SznON=_czepAccfsse7Q$(>9Wl?Ts954O;@ah^f3knRZ+P+cg?HvUNU>#R5mi1 zUS;?9eBI0~P0tV*UOJ0Yy2@=dBibtv-Y{f2JLO7ssJZdU&tXa)zsX3|vV~{agt2u& z|H>ZVZNs`D5s~%+v$`t`<{M+j9YpWrRqDRWmwPfx4$vJIU9&!VJA7{V81*wo-m({w^;o^b)=jfY(Pt3?vr>|1`7YU{W^ z0(8t4tOu!N?N;r7(o%M;2+`dM+WBz}JK|?YLB-KBeU3A09*d!kazv}Q7T!jeddbvw zLcw6HVp}%(o7S*G&uG3`6CLd^OAWo7+nk)Q+azUlo#Yzk#j~gE>!(9C%IA`!OBB~_ zq$=9Bj?zwwho?EM>xyG~^RyaAJJGv>dQ~?p_eUEn`;*V~4n=5-eXR`J84?iVPI9Od zOmxfxu)Q5hR%Fb+-(19O%>>7*&Z zHLBQE?_jXoQ*<*nkc`2C!v=3*q%M0ZKWsP2)+GPn*iCrVbDpTcjb6Ar}oiP^2py&(=edjIJssUzLOIkI zN8|B^I!>x@nP*LbSEZ5}C3alu-8L4gWR|uxs-x+$RYx<+`GnAXK9Pg|Hq+-*T)Dz? zcko|YH0HA$RVS}x32dSGx@SWx4yOZQTk+9~4WB@bW=L#xvee>WlsrSuZQUf}_j->? zat+u#)kHOSrupeT3`7={814~BBnjECxl#=wUWz7Oj5CrlqlS|2)x2?^qX(fscDjX7 ziaxVD&Pyhh{TeaT7%*+LwucoFxjE<8-md-eQv45}E zux#zEc0ql=Gc-C(Z^Ca45&hF=1NtKyBD(TV|X7+Fliy>)ZD_}1h#;dUo8E&_%{VB3pDqu!V^ds`X zP9n?iJxyEFtr3B>_ye|2+V$6lenT~*^CHh@h&OR`cHfEj*O#0nUpq0gZz4Ko%uhHz zI!0Meo8zRm21oz$mB5YMijLTwIc$zxr&tWz?hZNr5IMnfE3tNSqkZGCnM!A>ZsfHe z$9-X$~rmMFAWOV0zAZKWLh}x5!k}CiI>5QLn`_sn7ovrYFx z3QDJ0TMWbw`nN5POQ1y=C6Tnc#~|R?4Tgh#BQa5Hk!&|lvUNRTuQ3M1D_N>|XYPwx z?ASE#C*epXyir&Vmld4Oy*3;$@wvG#fL#J;QjQ07$@XO{oCo_Q5TrOlfArz^ITq=a z>1fw4=~A8S)(vvN(um?2Mrpgp_Ky>`J)nWeFDUzNH_#Q`qyFTMI*wE^oyKR&;&RjQ zm!VMy#48Dc0!;z#=xR$5&Y}4c*~2pedoJNSZx1=bT|&eT$MG4SG~9}hflUYzQp{1} zU|(n4`p|lPES#OCX!vQCq~!tkb3Frw)!<*pzQX(dV#Iyj1#OO&%fbxFFjSPr3CiWFD3A2DS0g%wf`vC1!)nUf?QiQ@-p; zw6I|!uB2~S^5F6_*;R*GA-?eL4YD@d`}RA8kK$VRLvjZlmRI(bIGYVe%4V)PhmM$f zYKu0R&I#yDP`(+7Ecp0dtM#Zfwy*A||J1V3=w55!IespCecxvFgnN20wu zIk8t-vzvJB)8L#hli8~nx)?4kMl$;?o~(s6>8A-Qypb0QA>m&X;rrdZ7cMX@)Wf-) z%6dd5P-FDs!pHg9*xBHb{I9*g%q>_BbaeJ#w3?WE_i`?~vM%#jsT@{find2jun%@V z5Zmvd?=7Lj^qVcY9pa$S_Tl$|a>x)#mq)U?+5vvJw8|S}IP#OPS@v=g${yFr^VP2J zJd%F%e8YpUbbRV<-&EW4uQ_dc5JtyYjB4T+(TR&jV{c2_iA(#59D5}L16?&MjZ@Ikboe~7+MGjNHQ3T=pq)1iVz?mFczfO1StVVN)QMrNJ|1yfkcG_ zC6EXqVQ)}&$1uB(fA-hHuRJ{G-0$9V-+Rt`ZdE;-1Ai-WynAPLFTlr}bdU8C-$!Zs zDsqxZ<);Vabh!StGmIl2lSCr|C8I{Lc#gd8Uv^(<<9t>Upa23}0lX$`9HxW_2N9t> z8%~ywA{lW@)ZI}}GGk_eot!c8?jldH-{)+D}ezz~>n(puc2%%f{u*baj zQ@D3^79sXpR%7U!{mjQK87j+z1{>GQ&{biRneAa==4*o3%(YF%Dp$5WzSVfHVx+oJ zG{V{M3WN+yn+TFH^5Rt!bgfnsj7>liJYq)x<|@Ny=J` zL+Fmq_8fXi9NZQ8wzDP21qVZz8~Yo1#*G1IyIGY~YOMD#o&gY9XIt}$5adwLtXsne z*6&ulslZ7qRpn2u4{0%_(9X{8gM>GHd?H`_%w>oa0r3YMqKj+F>`qd2^5)$6%nA}? z3g!sd%h3s%nEnPuRNzaGS>;O7hytIk9muD(i9-GypgcOCD1ml~qJh5l3*dOyA1WFl z0N0%5Kx(w+g!erhI5j--JU;w9=bBaM@98HrJ1qpJKAUt(+7dG6M!15#Q9hMI@JdVF z42ViKGaHYgi3^y1Q+3iLTIRqQ`S05BXaiT;r0FYf$n|@ruscDq9#7k$YK5)0^)mq4 z53xpNb4F$b^M>6$&u*t@w@crVekQ!VKC0%eYEsrHAPVqm4t`_<144Z;7<3?J=Awem zT@Il{d&H}_{b=I)N8L#=A$;^vCz*`GXBb6X~VY6W!6P`Ha78n{hOB`}w^a5~}*ggY! zMJm0hbri{;V;;ufBkOA=n`@X1JaewS9l=g@HB1V_n}!~>{6N{J3FC)wLLT&Cxv4sq zaqtLVUnO#-y5$Fhq_ASs-z)~@H0$Oj30L2hv($9c06){DBRag^BDIm}?}FciQhsdi z{RFP)_o)U1oBKDrh11y3_!j>t@OT8DdYQ@Rv4$sqBs7sxG1uH%lWC#p2Mgn`O+Tx= zmW7JDhItdRvqIsF6D( zF3M$1G?pJ45it%4{@@LTKkPf_1hCI#0^ z^$+LZR6EV!m=3Gif2jVHRr%)k8x(5Urs-Ps~Z5*#k3#TzAyL zI1yff&>_!4LImhl)#XSmi%=%wyA;6G4ne`?LU!oBpM{0q)nr0y=WHm0XFQ?Hovcmm z<_bqtjZeM!AS3dIxb7|wLapqSVBFIfVWoC+pnEnu+j--J3<}5Ey0zgXhunu7o6RCn z!{=bE+0KETY#{(<4MgM!r>R;hSHQN&s*so8D)mQDaISEhcHpJ?M=@7)e{&$?f0 zVHs@zZ{?oX`?5IR(OaBs2~Dt;424!iYk%wJqk%H0TJ-1??%+qQy3HPh+y_af$QuG~ zY%BohcwNUfEUEdz8(O1>6RDXvQ*(PPnj**7j=z@06%^L?^#=rsvKYP$E}?0}ylc?P~aIe}G0&Yd!;Mj(prU6)*9@hDcLs^4t!+54B?L+8T1clQKkTqvfdE5R7 z2AdT!W_8A|+>jylTMYP>4aru+=jOpFA0Ml=k0ocpDsir*&&@6g6{l-k2By%V=Fn&VI6)DwX$BIlxF`; z@9IE}>Y?4}ssq!+z-;+}?#oP?{ebP&W7Uo*xN}eo3&rAxq=$N6%5kz%kKktnRr)sP zI$m%wjQ`mUgfumJNiU&DkLfugTLk+-x4Kaa+ec}Bs&RA>#-zz*|5kuh^0h3=p}tOM zpU>8-NK5+w_Br$gkDd^wBb>~KA6`({*=}MT6jz`|J#*O6RtSWhNzkE+-YJ~PEUE*k zJw^>qF;GE=rB^COcokJrN*XVKD2ctwdsYsNtSK)f!-_j z+3&p5T1;7F!y52HPV09!8B3IpZ!*VA?at3FAmOoM-R6*I;yna$?{UPq(Ei+=3sy*x z1e&^0C8<5T@*OSgrS6C+KRTT$8mGCF-`t;BqAcptOUqrlfcfPvT^^+(U%5O=7p$=C zcvs0RJ6=%)TaKlRY-c%^itw;Zj{r;kZ;W@d`un^UD^~9{`{n18|6BGew+CE5^7;mj z(_!de(D7Pj5vYsIG%Z1*f))tjfHeYqB^l`#)Kx1SP1x#uU_<}j{M$T(tbj-{x~P0^ zpG43IQB*LPFGyVt7Gu5MOCA=d$jZ<5fwgW}P{UgNUHKGuEnhk4Qw-}OGiwROjFM!u zVAP=wi37QTQ+K1pKWFmtH%T2QySSmTPMe;((4TH8TJ69^*-g5Ty7jmJDBhm)pX(;N zx}tmJ4RNmQ%bY-zK5TPQ*0lpuwgURRT0SMqP;YhK2oY7!5ohBU>m?+DMu}Xg!}piN zZ>vc?-0@ZeETm^ko_4$Vo0J%JzgVvqX&xm6pDlYEs5b~BLwn48=l4wD2T8;wO*WNk zPvJS{7w>-haL2n+(a94sxDAePIuqh7UaU!vgy@J7Zbx!ya)A%U`i(rWqlNC&UU9*C znnVy290GMnZ004HtL3-WIr&vSsAM7isWdjK0x_Qsjy4Awo>KZ(1{HaE)f6wHdIckG z=ANNLmJ`oAf*DHA(o5%7@v8(soay&=LJ+N&V$Lr74{Y4r7 zt*81-A!S||+&di222;cAJHf~sb@Rkfu&i9Mwjkno8qB2)wrbnGdLxd@4LRt_3WyH8 zp<{GTfzlFR^7qDH#PQ~E&jf2uru$vVof|YCLd845wyxj6@vwvpjmZ#S?ibJQQdd@m z_SR0iU^MfOGm$DOfkfAniEXCw2>+>n8)(r|^=BhBDqnnmayr3Wkcf&OqcbK4Bqm)v zw}wbAiY%hmO-aJp2$2y|1fEv7RF-n~o!^+>gpmDhmw{LfzLD6!`n=i0IhF?R&=tQi z`ottEGOGrveXX@8LkHk2}vm&Qk6c?LYb z!)me5Mg~i@-{Luz7v~NqdcE5*C!T7r+IG|}uCdE~yD{57k!QdbZcq?w;yLze0A7P% z-R_}t{gFho< z>0n*_kB_XigB`30p(|D$aR=~O-f5*Q6ge88`gPL#rFZ4$mh|CM7Q0a#U5oB=q4dZC z3F$n-^T23N9LQ3Za>Om9$ALsEW^cFmj1wU$om7rgzH& zx04tA#9lJ1^Ow?@M?qEgbF1{0^zavjE>^VI&cwY3s)*kBg|QafC2lM0d!Q;?FwQtJ zfc^*h{@t0yK6~N~zfStm32=Q_EU}O*?s@;Zbl>l-9q@^y^skeCu`9DUx7nr7?@AB +#$#%#,#$#%#$#%#-#.#/ +CDE4 ++FGHIJKL !!!"#$#%#&'()*+#$#%#,#$#%#$#%#-#.#/& +MNOPQRS +#$#%#,#$#%#$#%#-#.#/? +6TUVWXYZ[\]Y^_`abcd]Y^_`abcd]Yefghijklmnopqrstuvwxyz{|} +~1 +( !!!"#$#%#&'()*+#$#%#,#$#%#$#%#-#.#/1 +(%##$#%#&'()*+#$#%#,#$#%#$#%#-#.#/ +# +! +## +  +## +&@ +7%##$#%#&'()*+#$#%#,#$#%#$#%#-#.#/L +C%##$#%#&'()*+#$#%#,#$#%#$#%#-#.#/8 +/########### +< +3########### ++ +"1 +(56789:;'*+#$#%#,#$#%#$#%#-#.#/+ +" p +g2%##$#%#&'*+#$#%# +  = +4#%##$#%#&'*+#$#%#,#$#%#$#%#-#.#/ +##6 +-23456789:;<=>?@AB +#$#%#,#$#%#$#%#-#.#/ ++ +" +  +E +  + +  +  +! +#.#/l +c%##$#%##$#%#,#$#%#$#%#-#.## +## +  E? +6 !!!"#$#%#&'*+#$#%#,#$#%#$#%#-#.#/ +  +  +  + ? +6#%##$#%#&'*+#$#%#,#$#%#$#%#-#.#/B +9%##$#%#&'()*+#$#%#,#$#%#$#%#-#.#/ +   + E  +  + E> +5 !!!"#$#%#&'*+#$#%#,#$#%#$#%#-#.#/ + +' +## + + + D ' +  +` +W%##$#%##$#%#,#$#%#$#%#-#.##########4 ++ !!!"#$#%#&'()*+#$#%#,#$#%#$#%#-#.#/ +! +##% +jklmnopqrstuvwxyz{|} + +  + + +56#-#.#/' +5 +, % +I +@#%##$#%#&'*+#$#%#,#$#%#$#%#-#.#/4 ++#.#/  + + + + +  + + D +;###########> +5%##$#%#&'()*+#$#%#,#$#%#$#%#-#.#/' +  + + ) + 2### + +# +#.#/ +  +   + 3 +*789:;'*+#$#%#,#$#%#$#%#-#.#/% + + E) + 1 +( # + +  +## + +! +5 +,' +##) +  +< +3########### +D8 +/23456789:=>?@AB +#$#%#,#$#%#$#%#-#.#/S +J5 +, + +56#-#.#/ + ! +## + +#.#/ +" +### +E + + +  + ++ +"\ +S%##$#%#&'()*+#$#%#,#$#%#$#%#-#.#/? +6`abcd]Y^_`abcd]Yefghjklmnopqrstuvwxyz{|} + + + + +6 +-23456789:;<=>?@AB +#$#%#,#$#%#$#%#-#.#/; +2xyz{|} + + (8"Ќ """"" "Þ"+"˧ +""Ԛ +">" +"3"(" +"  " +"  +" " +˜ +" " Ŀx" " t"" u""˸u""r""""""""""""Ο"""B""6"ת" "" +""܋"e""""$" +" 4" "!" """ ˱ "#N"! "$4"" "%:"#"&"$ǵ "'P"%е "(h"&Ȝ +")"' +"*"( "+") ","* +" "+Ü +"-",ɷ ".2"-ύ "/P".ʵ "'Y"/ +"0r"0Խ"1"1"2"2׆"3"3"45"4ˏ"5"5"6"6"7"7υ"8J"9"8Ӆ":"9ǻ ";": "<[";ψ +"=M"<ל +">"=՜ +"?"> "@"A"? "B"@ "C"A "D"B +" +"Ct""Du""E""F"E"G"Fa"H"G"I +"H<"J "I"K "J"L """Mє +"K"N"L"Oʔ +"M"P "N<"Qۿ "OS"Pm"Rݜ +"Q"SϨ +" +"T"E"U"R"V"S"W"T"X"Uj"Y"VQ"Z"W"["X"\"Y"]"Ut"^"Z"_"[p"`"\{"a"]o"b"^"c"_"d"Y"e"`S"f"a&"g"b}"hÅ +"c^"i +"dd"jѰ +"e:"k +"f0"l߀ +"g4"m +"h1"n +"iK"o +"j6"pӆ +"k-"qۯ +"l"rޯ +"m"s +"n"tÌ "o"u +"p"v +"q"w +"r"x +"s"y +"t]"z +"u"{ +"v"|޷ +"w"} +"xu"~"y""zE""{""| "}""~""""""" "" """""" +"" "%@"ɒ""r" ֒" +""1"ߒ"P""Ӡ"y"v""""5""""&"$"Q"$""!õ-""""O"`"S""͕""Օ""" """"""""""g"*""̅"e"Ӆ"""" ""۞ "" +"" +"0""""""""""""" ""׾ +""ЮB"" +"" +"" +"" +"" +"+""y""R"""""ϕ""""""""T""2"" """"" +""" +"|" """P""" +""ܖ +"" +"" +"D"" +"" +""ϼ +" "Á """"="" +"":" +"T" "d" +"M" "#"· ""ㅵ "n" "9"Ӹ "'"͸ "&" "4"͝ +"I" "B" +"""""""""i""""U"ߵ"~""""" "[" +"" +"_"t""u""""""$"D"$""!-""""O"7"S""""B"""""""" +"X""+"""""""" """""5"ٜ +""ǜ +")"֔ +""""""ß""""" """"""2"ϟ """"" ""㭇 ""܇ "" ""돇 ""㈇ ""ހ "B" +"p" "" ":" ""ۀ "#" "2" "i" ""ӈ "w" +"G"ƕ +"" +"" +"@""ų +"n" +"H" +" "u""5"""6"" +"q"Ç +""狰 """""""ɱ""Յ""" """""2" ""딭 "*"ʗ +""× +""""̙ " ""j"&"W""k"""x" "t""""׬"~""~" +""ߴ +"" +""x" """ż" """ """:""8" "/8"""""""""""ۧ""ǽ""績""""""X"""" ""׸ +""문 +""ۄ +""կ "" +"" +"-" +"V" "A"߲ +"3"ÿ<";"" +""<""=""="">""="" "" "" "B" """"r""""" +" +" +" +"Ñ +" " +" "ԏ"N"ʹ""""+"""ҽ"""" "v" +"" +"" +"""" +""4" +" ""~"t"""""""p"DZ"7""""b" """Ϩ +"" "" """"""ˌ"h"F""ۥ" ""`"ؒ"="ޒ""ޠ"y"""""" ""B""">"ˎ""ׇ"""""""""""""D"""""="<""="" +"" +"<" +" +" " +"" "/""i"u""""ۉf"|""΅"i""" +"&"Y" +"" +"dk"""""""""""" "2"ʗ +"" +""'"""""|"Г""""""" """ "B"е "(f""""""""" "" "Ǟ"" +"" +""ú"""" +"" +"""""""" +"\""" +"ӈ"""""" +""" +"" +""" +"˟""" """ה""""""""، +"" +"p"x""v""Dzv""Ϣv""u""ֈ""""""""Џ""ˏ"""""""("&""""""""׾"""~"B"l""Ϻ""" "" "!" +" +""""߈" "p";""""" ""ߧ +""""""""˟""ӕ" " +"d" +""7"߷""""""p"Ї""%""%"""""""" +"" +""˒"" "" "" "" "" "" +"" "4"ǖ """"ҏ"""""~"ג";"" +"" "ؾx" "u""*"""M""""7""""""""" "" ""˥ """"ߤ!"p""4""""""="?"":""5" """"""а""""ߏ"""l" +"E" +"" +""ۻ +"" +"m" +"Y""\" ""-""ג"6"e""ۧf"""΅"h"̡"""촫""̫""""""""NJ ";"O" "W" "" "8""""""""""" "" " " +""""f"|""""ē""ɕ""ҕ""=""ȿx" """"" +"B"֜ +">""" +"" +"" +"a" ""`"""ך"""""""""׎""""ӥ"""""""""ۈ""ۤ"L"""ȳ""ij""ó"o"""~"e"h"e"""*"ܩ"\"Ӝ">"""""ǀ"""r"! +""""t"" +">""""&"""""C"""㙊""""뒈"M"碈""""ǰ""""""ȶ"6"""""""""""""޳ "k"È ""ӏ"K"磿"" ""׃ +"" +"P"""""Ь"""E"ז"Y"[p" +"d`"x" "" """""̀""!"""ހ "I" "2" "u" "" +"r"""""""u"* * * + + *  *  * * * *  * + *  *  *  * * * *  !*"" #*$$ #*%% &*'' &*(( #*)) **++ **,, -*.. /*00 /*11 2*33 4*55 6*77 8* 99 :*!;; <*"== >*#?? <*$@@ A*%BB C*&DD 2*'EE F*(GG F*)HH **II *+JJ K*,LL K*-MM *.NN O*/PP Q*0RR S*1TT U*2VV W*3XX W*4YY Z*5[[ \*6]] \*7^^ \*8__ `*9aa b*:cc b*;dd e*<ff e*=gg h*>ii *?jj *@kk K*All K*Bmm K*Cnn K*Doo K*Epp q*Frr 4*Gss 6*Htt u*Ivv <*Jww >*Kxx y*Lzz {*M|| }*N~~ * O * P * +Q * R * S * T * U * V * W * X * Y * Z * [ * \ * ] * ^ * _ * ` * a * b * c * d * e * f * g * h * i * j * k * l * m * n * o * p * q * r * +s * t * u * v * w * x * y * z * { * | * } * ~ *  *  *  *  >*  >*  *  *  *  *  *  *  *  *  *  *  **  *  *  *  *  *  *  *  *  *  /*  /*  /*  *  *  *  *  *  *  *  *  *  *  *  2*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  S*  S*  *  *  *  *  *  *  *  *  *  *  *  *  2*  2*  *  *  *  *  *  *  *  S*  *  *  *  *  *  *  *  /*  *  /*  /*  /*  /*  *  *  *  *  *  *  \*  \*  *  *  *  *  *  *  *  *  W*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  W*  W*  *  y*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  >*  >*  <*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  q*  *  *  *  *  *  *  *  *  *  *  *  *  F*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  #*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  \*  *  *  *  *  *  *  {*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  /*  *  h*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  &*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  22samples2count2cpu2 nanoseconds2/usr/local/bin/kube-apiserver2runtime.heapBitsSetType2$/usr/local/go/src/runtime/mbitmap.go2runtime.mallocgc2#/usr/local/go/src/runtime/malloc.go2runtime.newobject2Gk8s.io/kubernetes/pkg/registry/networking/ingress/storage.NewREST.func122pkg/registry/networking/ingress/storage/storage.go2vendor/k8s.io/apiserver/pkg/util/flowcontrol/apf_controller.go2@k8s.io/apiserver/pkg/util/flowcontrol.(*configController).Handle2:vendor/k8s.io/apiserver/pkg/util/flowcontrol/apf_filter.go2Ck8s.io/apiserver/pkg/server/filters.WithPriorityAndFairness.func2.82Cvendor/k8s.io/apiserver/pkg/server/filters/priority-and-fairness.go2math/big.addMulVVW2(/usr/local/go/src/math/big/arith_arm64.s2math/big.nat.montgomery2!/usr/local/go/src/math/big/nat.go2math/big.nat.expNNMontgomery2math/big.nat.expNN2math/big.(*Int).Exp2!/usr/local/go/src/math/big/int.go2crypto/rsa.decrypt2#/usr/local/go/src/crypto/rsa/rsa.go2crypto/rsa.decryptAndCheck2crypto/rsa.signPSSWithSalt2#/usr/local/go/src/crypto/rsa/pss.go2crypto/rsa.SignPSS2crypto/rsa.(*PrivateKey).Sign2=crypto/tls.(*serverHandshakeStateTLS13).sendServerCertificate26/usr/local/go/src/crypto/tls/handshake_server_tls13.go21crypto/tls.(*serverHandshakeStateTLS13).handshake2"crypto/tls.(*Conn).serverHandshake20/usr/local/go/src/crypto/tls/handshake_server.go2#crypto/tls.(*Conn).handshakeContext2$/usr/local/go/src/crypto/tls/conn.go2#crypto/tls.(*Conn).HandshakeContext2net/http.(*conn).serve2$/usr/local/go/src/net/http/server.go22k8s.io/client-go/tools/cache.(*threadSafeMap).List28vendor/k8s.io/client-go/tools/cache/thread_safe_store.go2*k8s.io/client-go/tools/cache.(*cache).List2,vendor/k8s.io/client-go/tools/cache/store.go2$k8s.io/client-go/tools/cache.ListAll2.vendor/k8s.io/client-go/tools/cache/listers.go2Ak8s.io/client-go/listers/rbac/v1.(*clusterRoleBindingLister).List2=vendor/k8s.io/client-go/listers/rbac/v1/clusterrolebinding.go2ek8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac.(*ClusterRoleBindingLister).ListClusterRoleBindings2'plugin/pkg/auth/authorizer/rbac/rbac.go2Sk8s.io/kubernetes/pkg/registry/rbac/validation.(*DefaultRuleResolver).VisitRulesFor2$pkg/registry/rbac/validation/rule.go2Mk8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac.(*RBACAuthorizer).Authorize2Dk8s.io/apiserver/pkg/authorization/union.unionAuthzHandler.Authorize28vendor/k8s.io/apiserver/pkg/authorization/union/union.go2>k8s.io/apiserver/pkg/endpoints/filters.WithAuthorization.func12>vendor/k8s.io/apiserver/pkg/endpoints/filters/authorization.go2net/http.HandlerFunc.ServeHTTP2?k8s.io/apiserver/pkg/endpoints/filterlatency.trackStarted.func12Dvendor/k8s.io/apiserver/pkg/endpoints/filterlatency/filterlatency.go2Ak8s.io/apiserver/pkg/endpoints/filterlatency.trackCompleted.func12Ck8s.io/apiserver/pkg/server/filters.WithPriorityAndFairness.func2.92Fk8s.io/apiserver/pkg/util/flowcontrol.(*configController).Handle.func22Rk8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset.(*request).Finish.func12Mvendor/k8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset/queueset.go2Lk8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset.(*request).Finish2Ak8s.io/apiserver/pkg/server/filters.WithPriorityAndFairness.func22>k8s.io/apiserver/pkg/endpoints/filters.WithImpersonation.func12>vendor/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go2?k8s.io/apiserver/pkg/endpoints/filters.withAuthentication.func12?vendor/k8s.io/apiserver/pkg/endpoints/filters/authentication.go2Ek8s.io/apiserver/pkg/server/filters.(*timeoutHandler).ServeHTTP.func125vendor/k8s.io/apiserver/pkg/server/filters/timeout.go2runtime.memmove2)/usr/local/go/src/runtime/memmove_arm64.s2runtime.copystack2"/usr/local/go/src/runtime/stack.go2runtime.newstack2runtime.mapaccess2_fast642'/usr/local/go/src/runtime/map_fast64.go2[github.com/prometheus/client_golang/prometheus.(*metricMap).getMetricWithHashAndLabelValues2type..eq.k8s.io/apiserver/pkg/util/flowcontrol.watchIdentifier22runtime.mapaccess12 /usr/local/go/src/runtime/map.go2Mk8s.io/apiserver/pkg/util/flowcontrol.(*watchTracker).GetInterestedWatchCount2=vendor/k8s.io/apiserver/pkg/util/flowcontrol/watch_tracker.go2Ok8s.io/apiserver/pkg/util/flowcontrol/request.(*mutatingWorkEstimator).estimate2Ovendor/k8s.io/apiserver/pkg/util/flowcontrol/request/mutating_work_estimator.go2Lk8s.io/apiserver/pkg/util/flowcontrol/request.WorkEstimatorFunc.EstimateWork2=vendor/k8s.io/apiserver/pkg/util/flowcontrol/request/width.go2Gk8s.io/apiserver/pkg/util/flowcontrol/request.(*workEstimator).estimate2Ck8s.io/apiserver/pkg/server/filters.WithPriorityAndFairness.func2.22Csigs.k8s.io/structured-merge-diff/v4/schema.(*Schema).FindNamedType2>vendor/sigs.k8s.io/structured-merge-diff/v4/schema/elements.go2Hsigs.k8s.io/structured-merge-diff/v4/schema.(*Schema).resolveNoOverrides2=sigs.k8s.io/structured-merge-diff/v4/schema.(*Schema).Resolve28sigs.k8s.io/structured-merge-diff/v4/typed.resolveSchema2sigs.k8s.io/structured-merge-diff/v4/typed.TypedValue.Validate2:vendor/sigs.k8s.io/structured-merge-diff/v4/typed/typed.go22sigs.k8s.io/structured-merge-diff/v4/typed.AsTyped2Gsigs.k8s.io/structured-merge-diff/v4/typed.ParseableType.FromStructured2;vendor/sigs.k8s.io/structured-merge-diff/v4/typed/parser.go2Sk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*typeConverter).ObjectToTyped2Lvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/typeconverter.go2Uk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*structuredMergeManager).Update2Nvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/structuredmerge.go2Ok8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*stripMetaManager).Update2Hvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/stripmeta.go2Sk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*managedFieldsUpdater).Update2Svendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/managedfieldsupdater.go2Vk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*buildManagerInfoManager).Update2Ovendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/buildmanagerinfo.go2Qk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*capManagersManager).Update2Jvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/capmanagers.go2Tk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*skipNonAppliedManager).Update2Mvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/skipnonapplied.go2Qk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*lastAppliedManager).Update2Qvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/lastappliedmanager.go2Qk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*lastAppliedUpdater).Update2Qvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/lastappliedupdater.go2Kk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*FieldManager).Update2Kvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go2Sk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*FieldManager).UpdateNoErrors2>k8s.io/apiserver/pkg/endpoints/handlers.UpdateResource.func1.128vendor/k8s.io/apiserver/pkg/endpoints/handlers/update.go2Lk8s.io/apiserver/pkg/registry/rest.(*defaultUpdatedObjectInfo).UpdatedObject23vendor/k8s.io/apiserver/pkg/registry/rest/update.go2Dk8s.io/apiserver/pkg/registry/generic/registry.(*Store).Update.func12>vendor/k8s.io/apiserver/pkg/registry/generic/registry/store.go27k8s.io/apiserver/pkg/storage/etcd3.(*store).updateState22vendor/k8s.io/apiserver/pkg/storage/etcd3/store.go2k8s.io/apiserver/pkg/storage/cacher.(*Cacher).GuaranteedUpdate2Uk8s.io/apiserver/pkg/registry/generic/registry.(*DryRunnableStorage).GuaranteedUpdate2?vendor/k8s.io/apiserver/pkg/registry/generic/registry/dryrun.go2>k8s.io/apiserver/pkg/registry/generic/registry.(*Store).Update2>k8s.io/apiserver/pkg/endpoints/handlers.UpdateResource.func1.42>k8s.io/apiserver/pkg/endpoints/handlers.UpdateResource.func1.52Dk8s.io/apiserver/pkg/endpoints/handlers/finisher.finishRequest.func12Cvendor/k8s.io/apiserver/pkg/endpoints/handlers/finisher/finisher.go2 runtime.futex2+/usr/local/go/src/runtime/sys_linux_arm64.s2runtime.futexsleep2%/usr/local/go/src/runtime/os_linux.go2runtime.notesleep2'/usr/local/go/src/runtime/lock_futex.go2 runtime.mPark2!/usr/local/go/src/runtime/proc.go2 runtime.stopm2runtime.findRunnable2runtime.schedule2runtime.park_m2 runtime.mcall2%/usr/local/go/src/runtime/asm_arm64.s2vendor/google.golang.org/grpc/internal/transport/controlbuf.go2>google.golang.org/grpc/internal/transport.newHTTP2Client.func32@vendor/google.golang.org/grpc/internal/transport/http2_client.go2runtime.makeslice2"/usr/local/go/src/runtime/slice.go2 path.Join2/usr/local/go/src/path/path.go2;k8s.io/kube-openapi/pkg/handler3.constructServerRelativeURL22vendor/k8s.io/kube-openapi/pkg/handler3/handler.go2@k8s.io/kube-openapi/pkg/handler3.(*OpenAPIService).getGroupBytes2Bk8s.io/kube-openapi/pkg/handler3.(*OpenAPIService).HandleDiscovery28k8s.io/apiserver/pkg/server/mux.(*pathHandler).ServeHTTP26vendor/k8s.io/apiserver/pkg/server/mux/pathrecorder.go2vendor/github.com/prometheus/client_golang/prometheus/gauge.go2@k8s.io/component-base/metrics.(*GaugeVec).WithLabelValuesChecked2-vendor/k8s.io/component-base/metrics/gauge.go29k8s.io/component-base/metrics.(*GaugeVec).WithLabelValues2=k8s.io/apiserver/pkg/storage/etcd3/metrics.RecordEtcdBookmark2k8s.io/kube-aggregator/pkg/apiserver.(*proxyHandler).ServeHTTP2k8s.io/apiserver/pkg/storage/cacher.(*Cacher).startDispatching2;k8s.io/apiserver/pkg/storage/cacher.(*Cacher).dispatchEvent2.golang.org/x/net/http2.(*Framer).readMetaFrame2Xk8s.io/apiserver/pkg/authentication/group.(*AuthenticatedGroupAdder).AuthenticateRequest2Mvendor/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go2`k8s.io/apiserver/pkg/authentication/request/union.(*unionAuthRequestHandler).AuthenticateRequest2Avendor/k8s.io/apiserver/pkg/authentication/request/union/union.go2 runtime.ready2runtime.goready.func12runtime.systemstack2runtime.goready2 runtime.send2runtime.selectgo2#/usr/local/go/src/runtime/select.go2:golang.org/x/net/http2.(*serverConn).writeFrameFromHandler29golang.org/x/net/http2.(*serverConn).writeDataFromHandler28golang.org/x/net/http2.(*responseWriterState).writeChunk2(golang.org/x/net/http2.chunkWriter.Write2bufio.(*Writer).Flush2.golang.org/x/net/http2.(*responseWriter).Flush2Pk8s.io/apiserver/pkg/endpoints/responsewriter.outerWithCloseNotifyAndFlush.Flush2@k8s.io/apiserver/pkg/endpoints/handlers.(*WatchServer).ServeHTTP27vendor/k8s.io/apiserver/pkg/endpoints/handlers/watch.go22k8s.io/apiserver/pkg/endpoints/handlers.serveWatch2k8s.io/kubernetes/pkg/registry/rbac/validation.describeSubject2Tk8s.io/kubernetes/pkg/registry/rbac/validation.(*clusterRoleBindingDescriber).String2Mk8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac.(*authorizingVisitor).visit2 runtime.read2Gk8s.io/apiserver/pkg/storage/cacher.(*cacheWatcher).convertToWatchEvent2Gk8s.io/apiserver/pkg/storage/cacher.(*cacheWatcher).sendWatchCacheEvent2;k8s.io/apiserver/pkg/storage/cacher.(*cacheWatcher).process2Ck8s.io/apiserver/pkg/storage/cacher.(*cacheWatcher).processInterval2sigs.k8s.io/structured-merge-diff/v4/fieldpath.NewVersionedSet2Avendor/sigs.k8s.io/structured-merge-diff/v4/fieldpath/managers.go2google.golang.org/grpc/internal/transport.(*controlBuffer).put2Kgoogle.golang.org/grpc/internal/transport.(*http2Client).handleWindowUpdate2runtime.chansend12:k8s.io/apiserver/pkg/storage/cacher.(*Cacher).processEvent2Gk8s.io/apiserver/pkg/storage/cacher.(*watchCache).UpdateResourceVersion29vendor/k8s.io/apiserver/pkg/storage/cacher/watch_cache.go2)k8s.io/client-go/tools/cache.watchHandler20vendor/k8s.io/client-go/tools/cache/reflector.go26k8s.io/client-go/tools/cache.(*Reflector).ListAndWatch2:k8s.io/apiserver/pkg/storage/cacher.(*Cacher).startCaching2?k8s.io/apiserver/pkg/storage/cacher.NewCacherFromConfig.func1.124k8s.io/apimachinery/pkg/util/wait.BackoffUntil.func120vendor/k8s.io/apimachinery/pkg/util/wait/wait.go2.k8s.io/apimachinery/pkg/util/wait.BackoffUntil2-k8s.io/apimachinery/pkg/util/wait.JitterUntil2'k8s.io/apimachinery/pkg/util/wait.Until2=k8s.io/apiserver/pkg/storage/cacher.NewCacherFromConfig.func12%crypto/tls.marshalCertificate.func1.122/usr/local/go/src/crypto/tls/handshake_messages.go2Avendor/golang.org/x/crypto/cryptobyte.(*Builder).callContinuation2B/usr/local/go/src/vendor/golang.org/x/crypto/cryptobyte/builder.go2Bvendor/golang.org/x/crypto/cryptobyte.(*Builder).addLengthPrefixed2Hvendor/golang.org/x/crypto/cryptobyte.(*Builder).AddUint24LengthPrefixed2#crypto/tls.marshalCertificate.func12crypto/tls.marshalCertificate2/crypto/tls.(*certificateMsgTLS13).marshal.func12)crypto/tls.(*certificateMsgTLS13).marshal2runtime.newproc12runtime.newproc.func12runtime.newproc23k8s.io/apimachinery/pkg/util/wait.ContextForChannel24k8s.io/apimachinery/pkg/util/wait.PollImmediateUntil2-k8s.io/client-go/tools/cache.WaitForCacheSync26vendor/k8s.io/client-go/tools/cache/shared_informer.go2Dk8s.io/client-go/informers.(*sharedInformerFactory).WaitForCacheSync2,vendor/k8s.io/client-go/informers/factory.go2math/big.mulAddVWW2math/big.nat.divBasic2$/usr/local/go/src/math/big/natdiv.go2math/big.nat.divLarge2math/big.nat.div2crypto/rsa.encrypt2crypto/rsa.VerifyPKCS1v152(/usr/local/go/src/crypto/rsa/pkcs1v15.go2crypto/x509.checkSignature2%/usr/local/go/src/crypto/x509/x509.go2-crypto/x509.(*Certificate).CheckSignatureFrom2,crypto/x509.(*Certificate).buildChains.func12'/usr/local/go/src/crypto/x509/verify.go2&crypto/x509.(*Certificate).buildChains2!crypto/x509.(*Certificate).Verify2Uk8s.io/apiserver/pkg/authentication/request/x509.(*Authenticator).AuthenticateRequest2?vendor/k8s.io/apiserver/pkg/authentication/request/x509/x509.go2 time.sendTime2runtime.runOneTimer2!/usr/local/go/src/runtime/time.go2runtime.runtimer2runtime.checkTimers2runtime.stealWork2 bytes.(*Buffer).tryGrowByReslice2bytes.(*Buffer).Write2Cgoogle.golang.org/grpc/internal/transport.(*http2Client).handleData2crypto/tls.(*Conn).Handshake2runtime.unlock22runtime.unlockWithRank2)/usr/local/go/src/runtime/lockrank_off.go2runtime.unlock2runtime.selunlock2runtime.selectgo.func32=go.etcd.io/etcd/client/v3.(*watchGrpcStream).serveWatchClient2)vendor/go.etcd.io/etcd/client/v3/watch.go2crypto/sha256.sha256block23/usr/local/go/src/crypto/sha256/sha256block_arm64.s2crypto/sha256.block24/usr/local/go/src/crypto/sha256/sha256block_arm64.go2crypto/sha256.(*digest).Write2)/usr/local/go/src/crypto/sha256/sha256.go2time.Time.AppendFormat2 /usr/local/go/src/time/format.go2time.Time.Format2net/http.setLastModified2 /usr/local/go/src/net/http/fs.go2net/http.serveContent2net/http.ServeContent2Wk8s.io/kube-openapi/pkg/handler.(*OpenAPIService).RegisterOpenAPIVersionedService.func121vendor/k8s.io/kube-openapi/pkg/handler/handler.go2google.golang.org/grpc.recv2)vendor/google.golang.org/grpc/rpc_util.go2+google.golang.org/grpc.(*csAttempt).recvMsg24google.golang.org/grpc.(*clientStream).RecvMsg.func12.google.golang.org/grpc.(*clientStream).RecvMsg2Mgithub.com/grpc-ecosystem/go-grpc-prometheus.(*monitoredClientStream).RecvMsg2google.golang.org/protobuf/internal/impl.legacyLoadMessageInfo2Avendor/google.golang.org/protobuf/internal/impl/legacy_message.go2:google.golang.org/protobuf/internal/impl.legacyWrapMessage2@google.golang.org/protobuf/internal/impl.Export.ProtoMessageV2Of2=vendor/google.golang.org/protobuf/internal/impl/api_export.go2*github.com/golang/protobuf/proto.MessageV220vendor/github.com/golang/protobuf/proto/proto.go2/github.com/golang/protobuf/proto.UnmarshalMerge2/vendor/github.com/golang/protobuf/proto/wire.go2*github.com/golang/protobuf/proto.Unmarshal25google.golang.org/grpc/encoding/proto.codec.Unmarshal25vendor/google.golang.org/grpc/encoding/proto/proto.go2*encoding/json.(*decodeState).rescanLiteral2)/usr/local/go/src/encoding/json/decode.go2"encoding/json.(*decodeState).value2#encoding/json.(*decodeState).object2&encoding/json.(*decodeState).unmarshal2encoding/json.Unmarshal2Wk8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator.(*Downloader).OpenAPIV3Root2ek8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator.(*specProxier).updateAPIServiceSpecLocked2Pvendor/k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator/aggregator.go2_k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator.(*specProxier).UpdateAPIServiceSpec2Nk8s.io/kube-aggregator/pkg/controllers/openapiv3.(*AggregationController).sync2Evendor/k8s.io/kube-aggregator/pkg/controllers/openapiv3/controller.go2]k8s.io/kube-aggregator/pkg/controllers/openapiv3.(*AggregationController).processNextWorkItem2Sk8s.io/kube-aggregator/pkg/controllers/openapiv3.(*AggregationController).runWorker20go.etcd.io/etcd/client/v3.(*watchGrpcStream).run2net/url.escape2net/url.QueryEscape2net/url.Values.Encode2runtime.(*waitq).dequeue2regexp.(*Regexp).tryBacktrack2%/usr/local/go/src/regexp/backtrack.go2regexp.(*Regexp).backtrack2regexp.(*Regexp).doExecute2 /usr/local/go/src/regexp/exec.go2regexp.(*Regexp).replaceAll2"/usr/local/go/src/regexp/regexp.go2!regexp.(*Regexp).ReplaceAllString2,gopkg.in/square/go-jose%2ev2.stripWhitespace2-vendor/gopkg.in/square/go-jose.v2/encoding.go2(gopkg.in/square/go-jose%2ev2.ParseSigned2(vendor/gopkg.in/square/go-jose.v2/jws.go2*gopkg.in/square/go-jose.v2/jwt.ParseSigned2,vendor/gopkg.in/square/go-jose.v2/jwt/jwt.go2Ok8s.io/kubernetes/pkg/serviceaccount.(*jwtTokenAuthenticator).AuthenticateToken2pkg/serviceaccount/jwt.go2Zk8s.io/apiserver/pkg/authentication/token/union.(*unionAuthTokenHandler).AuthenticateToken2?vendor/k8s.io/apiserver/pkg/authentication/token/union/union.go2ek8s.io/apiserver/pkg/authentication/token/cache.(*cachedTokenAuthenticator).doAuthenticateToken.func12Tvendor/k8s.io/apiserver/pkg/authentication/token/cache/cached_token_authenticator.go24golang.org/x/sync/singleflight.(*Group).doCall.func225vendor/golang.org/x/sync/singleflight/singleflight.go2.golang.org/x/sync/singleflight.(*Group).doCall2runtime.entersyscall_sysmon2-runtime.(*gcControllerState).heapGoalInternal2%/usr/local/go/src/runtime/mgcpacer.go2$runtime.(*gcControllerState).trigger2runtime.gcTrigger.test2 /usr/local/go/src/runtime/mgc.go2/golang.org/x/net/http2.(*serverConn).readFrames2&crypto/tls.(*prefixNonceAEAD).Overhead2-/usr/local/go/src/crypto/tls/cipher_suites.go2)crypto/tls.(*Conn).maxPayloadSizeForWrite2runtime.findfunc2#/usr/local/go/src/runtime/symtab.go2Fk8s.io/apiserver/pkg/server/filters.(*requestWatermark).recordMutating21k8s.io/apiserver/pkg/storage/etcd3.(*store).Count23k8s.io/apiserver/pkg/storage/cacher.(*Cacher).Count2Jk8s.io/apiserver/pkg/registry/generic/registry.(*DryRunnableStorage).Count2Qk8s.io/apiserver/pkg/registry/generic/registry.(*Store).startObservingCount.func12.golang.org/x/net/http2.(*ClientConn).RoundTrip2*vendor/golang.org/x/net/http2/transport.go20golang.org/x/net/http2.(*Transport).RoundTripOpt2-golang.org/x/net/http2.(*Transport).RoundTrip25golang.org/x/net/http2.noDialH2RoundTripper.RoundTrip2net/http.(*Transport).roundTrip2'/usr/local/go/src/net/http/transport.go2net/http.(*Transport).RoundTrip2'/usr/local/go/src/net/http/roundtrip.go2>k8s.io/client-go/transport.(*bearerAuthRoundTripper).RoundTrip23vendor/k8s.io/client-go/transport/round_trippers.go2=k8s.io/client-go/transport.(*userAgentRoundTripper).RoundTrip2 net/http.send2$/usr/local/go/src/net/http/client.go2net/http.(*Client).send2net/http.(*Client).do2net/http.(*Client).Do2(k8s.io/client-go/rest.(*Request).request2'vendor/k8s.io/client-go/rest/request.go2#k8s.io/client-go/rest.(*Request).Do2;k8s.io/client-go/kubernetes/typed/core/v1.(*namespaces).Get2=vendor/k8s.io/client-go/kubernetes/typed/core/v1/namespace.go2:k8s.io/kubernetes/pkg/controlplane.createNamespaceIfNeeded2pkg/controlplane/client_util.go2Hk8s.io/kubernetes/pkg/controlplane.(*Controller).UpdateKubernetesService2pkg/controlplane/controller.go2Kk8s.io/kubernetes/pkg/controlplane.(*Controller).RunKubernetesService.func221k8s.io/apimachinery/pkg/util/wait.NonSlidingUntil2Ek8s.io/kubernetes/pkg/controlplane.(*Controller).RunKubernetesService2net/url.shouldEscape2\k8s.io/apiserver/pkg/authentication/request/bearertoken.(*Authenticator).AuthenticateRequest2Mvendor/k8s.io/apiserver/pkg/authentication/request/bearertoken/bearertoken.go23golang.org/x/net/http2/hpack.(*Encoder).searchTable2runtime.(*mspan).nextFreeIndex2runtime.slicebytetostring2#/usr/local/go/src/runtime/string.go2strconv.quoteWith2"/usr/local/go/src/strconv/quote.go2 strconv.Quote2 runtime.full2 crypto/sha256.(*digest).checkSum2crypto/sha256.(*digest).Sum2crypto/rsa.emsaPSSEncode2Gk8s.io/apimachinery/pkg/apis/meta/v1.(*ObjectMeta).MarshalToSizedBuffer2;vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go28k8s.io/api/coordination/v1.(*Lease).MarshalToSizedBuffer21vendor/k8s.io/api/coordination/v1/generated.pb.go2:k8s.io/apimachinery/pkg/runtime.(*Unknown).NestedMarshalTo25vendor/k8s.io/apimachinery/pkg/runtime/types_proto.go2Jk8s.io/apimachinery/pkg/runtime/serializer/protobuf.(*Serializer).doEncode2Fvendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go2Hk8s.io/apimachinery/pkg/runtime/serializer/protobuf.(*Serializer).encode2Hk8s.io/apimachinery/pkg/runtime/serializer/protobuf.(*Serializer).Encode2Gk8s.io/apimachinery/pkg/runtime/serializer/versioning.(*codec).doEncode2Ek8s.io/apimachinery/pkg/runtime/serializer/versioning.(*codec).encode2Ek8s.io/apimachinery/pkg/runtime/serializer/versioning.(*codec).Encode2Gk8s.io/apiserver/pkg/endpoints/handlers/responsewriters.SerializeObject2Ivendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go2Sk8s.io/apiserver/pkg/endpoints/handlers/responsewriters.WriteObjectNegotiated.func22?k8s.io/apiserver/pkg/endpoints/request.(*durationTracker).Track2Avendor/k8s.io/apiserver/pkg/endpoints/request/webhook_duration.go2Jk8s.io/apiserver/pkg/endpoints/request.TrackSerializeResponseObjectLatency2Mk8s.io/apiserver/pkg/endpoints/handlers/responsewriters.WriteObjectNegotiated2?k8s.io/apiserver/pkg/endpoints/handlers.transformResponseObject2:vendor/k8s.io/apiserver/pkg/endpoints/handlers/response.go28k8s.io/apimachinery/pkg/apis/meta/v1.Time.ToUnstructured23vendor/k8s.io/apimachinery/pkg/apis/meta/v1/time.go2Osigs.k8s.io/structured-merge-diff/v4/value.TypeReflectCacheEntry.ToUnstructured2Avendor/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache.go2@sigs.k8s.io/structured-merge-diff/v4/value.(*valueReflect).reuse2Avendor/sigs.k8s.io/structured-merge-diff/v4/value/valuereflect.go2Dsigs.k8s.io/structured-merge-diff/v4/value.(*valueReflect).mustReuse2;golang.org/x/net/http2.(*serverConn).processFrameFromReader2*golang.org/x/net/http2.(*serverConn).serve2sync.(*entry).load23go.etcd.io/etcd/api/v3/etcdserverpb.(*kVClient).Txn2.go.etcd.io/etcd/client/v3.(*retryKVClient).Txn2'go.etcd.io/etcd/client/v3.(*txn).Commit2'vendor/go.etcd.io/etcd/client/v3/txn.go2runtime.siftdownTimer2runtime.dodeltimer0H􂙤PoZ`p \ No newline at end of file diff --git a/catalogd/pprof/kubeapiserver_alone_heap_profile.pb b/catalogd/pprof/kubeapiserver_alone_heap_profile.pb new file mode 100644 index 0000000000000000000000000000000000000000..1bc87a15021a891d9fdd6f93469aa5a58bbc79f7 GIT binary patch literal 402317 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

    $W{A0zx#)!|9l_qU;Q@aGqHzDB0ucZ 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 literal 0 HcmV?d00001 diff --git a/catalogd/pprof/kubeapiserver_cpu_profile.pb b/catalogd/pprof/kubeapiserver_cpu_profile.pb new file mode 100644 index 000000000..b5cf7fa78 --- /dev/null +++ b/catalogd/pprof/kubeapiserver_cpu_profile.pb @@ -0,0 +1,290 @@ + + + + + + +   + + + ! + "#$%&'(& +)*+,-./01234567! +89  + :;<=>?@A +"BCDE& +FGHIJKLM +NOPQRSTUVWXYZ ! + [\]^_=>?@AU +L`ab]cdefghijklmnopqrstuvwxyz{|}~         4 ++           +]& +] +NOQRTUVWXYZ ! +QRTUVWXYZ !8 +/R   +  +b] + + +RTUVWXYZ ! ) +    +] +QRTUVWXYZ !" +"#$%& + +"#$%&'(' +   # +  6 +-]           +QRTUVWXYZ !# + + ] + b]# +   +PQRTUVWXYZ !1 +(           + +% +  S +JGHI          & +"#3 +_=>?@A + +5 +,   +_=>?@A +OPQRSTUVWXYZ !c +Zfghijklmnopqrs                +;<=>?@A? +6HIJK           + +NOQRTUVWXYZ ! d +[klmnopqrs               P +G}~              K +B +  + * + +QRSTUVWXYZ !5 +, +)*+,-./012 + +Z ! + 7 + +] + +PQRTUVWXYZ !1 +( +"#$%&E +<|}~               +CDE +  ' +"#$%& +NPQRSTUVWXYZ ! +QRSTUVWXYZ !F +=              + +   + +""#$_=>?@A +   + +NOQRSTUVWXYZ ! e +\Y +PR             - +$   + !+ +""#$_=?@A +   + HI +   +OQRTUVWXYZ !6 +-          0 +']f +]] +! +  +   +RTUVWXYZ !] +Tfghijklmnopqrstuvwxyz{|}~            V +M +9% +   V +M{|}~               +RTUVWXYZ !T +K{|}~                 +  + ] + +6 +-           + !] +Tdefghijklmnopqrs                 +  + + +E +  + + ! +QRTUVWXYZ !7 +.ab]defghijklmnopqrst + + +QRSTUVWXYZ !j +aklmnopqrs               = +4 + + +Z ! +]" +_=>?@A +  +% +   +    +  +RUVWXYZ !2 +)b  +  !Y +PGHIJK             ? +6"#$%&           ( +? + + 1YZ !3 +*NR   +-./012 +QRTUVWXYZ !(8"""""""""""""㠻""""  " " +" +" ""  +" 2" "  +"" "" ""۞ "" +"" +"+"""̣"" +"""ø +"" "4"ǖ """"""""׆""㸕"""" ""!"""+" ת"# "!"$ +"%"""&"#"'R"$"("%")"&ϕ"*"'"+"("")","*"-&"+$".Q",$"/"-õ-"0"1"2".O"3`"/S"4"0͕"5"1Օ"6"2"7 "3X"8"4"9"5":"6";D"7"<"8"=,">,"9"":Δ"?";Ӕ"@"<""=""A +">X"B"?+"C"@"D"E"A""B"FE"C"G"D"H "I"E""F"JU"Gˏ"K"H"L"I"M"J"N"O"K"P"L "Q"M׾ +"R"NĿx"S"Ot"T"Pu"U"Q˸u"V"Rr"W"S"X"T"Y"U"Z"V"["W"\"XΟ"]"Y"^B"Z""6"["_i"\"`"]"a "^׿"b"_""`܄""aϟ "c"b"`"c"d"e"d "f"e㭇 "g"f܇ "h"g "i"h돇 "j"i㈇ "k"jހ "lB"k +"mp"l "n"m "o:"n "p"oۀ "q#"p "r2"q "si"r "t"sӈ "uw"t +"vG"uƕ +"w"v +"x"w +"y@"z"xų +"{n"y +"|H"z +"} "{Á "~"|""} +"""~ +"|" ""е "h" "@"ǵ "P"Ȝ +"" +"" "" "" +""Ü +""ɷ "2"Խ""""ﳝ +")" "#"· ""ㅵ "n" "9"Ӹ "'"͸ "&" "4"͝ +"I" "B" +"""""""""`"̗ +""× +"""" "m" """""`""" +""9" +"" +"p" +"\""""""""\"u"U""X"x"S"t"T"*""p"""v""Dzv""Ϣv""u"V"ֈ""""""""Џ""ˏ"""""""8""(" "8"ʵ "Y" +"r""i""""U"ߵ"" "c"秜 "1"˧ +""Ե""""""""x""v"""X"'"""  ""`"" "9""۶9" """""޲""""ڱ""ȱ""Յ"""" +"0" "0"1" ""  "x"S"ӕ" """ה""Ⱦ" "Ծ" +"¾" "׏""""ҽ"""%"""""""""%""%"""""""" +"" +"""""""" ""`""g"*""̅"e"Ӆ"" "" "" "" +"" +""ύ "P"t"T""B""H""""5"""""""Ӛ"f""" +":""ߗ +""ʗ +"""""˅"""" "2" "c""j"&"W""k""""" """"f"|""΅"i"t"T"ܚ +">" +"3"(" +" """"""߼@"""ߦ +""""""g""""|""?"!""""Ǚ""" """"J5"υ"J""Ӆ""ǻ "" "["ψ +"M"ל +""՜ +"" """ "" """y"߈" "p";"""""ۧ""ǽ""績""""""""Ǿ"""""",""O"7"S""""B"""b"*""""""p""" +"_" +"Y""Ӽ""" """""߹""ڹ""ȼ" """"""""""ǔ""㘊""""":"""""-"1""߂ " " "" "" ""׭ "g" +"" +"" +""Ç +""狰 ""֔ +"""p"DZ"7"""Δ"?"""""K" "" """"""Ӿ" +"""u"U""`"""F""F""F""ό "" ""ހ "lI""U""""~""'""""""E"""箭"""Z""""""""Y"""""׭ +"0" +"" +"k"Ѱ +":" +"0"߀ +"4" +"1" +"K" +"6"ӆ +"-"ۯ +""ޯ +"" +""Ì "" +"" +"" +"" +"" +"]" +"" +""޷ +"" +"u"Ԧ "" "" "h" "" +""""׬"~"º"""" +"" +"" +"\""t"T"u"U"Ԡ*">"*"" +"" +"" +"`""%""%"Ǽ +"_""7" +"E" +""""""""}"""""" "" """п""Y"ߏp"0"p","ӓ""͔""ß"""^?"B"k"""M"""""""Խ""""""`"ߧ +"""d"""""  ""g""" +"Y""""""""""" "~""F>"""" "Þ""""""""&"""""""""""`"u"D""u"U" ""˱ "N" "4" ":""~"" "p"""" +""""""""$".D"$"" -""1""""х"x"""u"U"ʳ"#""f"""ͬ"""E""Y""""""""t"=""u"V" +"V" "A"߲ +"3" "/""""""""H"ǿ"#""/"""䱚""" """""""" +"""H"è+""*" "*"I"*"0"҅""}"" +"""˅"""""""""""˿"""""`"ׄ"e"˶"Y"" ""߃ "" "" "`" "/" "" "8""""""" +"E" +"" +""ۻ +"" +"m""""."ߵ"."""x"""N" "~"""㯪"""""m""""""t""Q""S""&""}"Å +"^" +"`"">,"̀"""""!"ז" """ +"\"ͷ +"T"" +" "иv""""˾"""""""" +"s""" """"" "p""׾"""""""" +"Ú":"""d"e"̘""Ϧ +"" +"c""<"""0"(""" """&""I"""˛ """0""" "t"T"""G""""""e" +"" +"" +"a" """""" "e" "A"""׵"""z"ǃ"("""-"ό "" " " ""ހ "lF"!""""В""딭 "*"Ϩ +""Ԣ"""Β""" ג" ""9"ޒ""ޠ"y"""""^5"ؒ"&"Ж""""","T"׀-"Y""""Ѿ" +""""""""""""9"ӹ"$""8" +"" +" ""`""r"3""3""˔ "(""Y" "a"c"" """"""""""""""" +"""@""秚"""""""l""" +"d" "d" +"M""""""""""""D"" "" ""˥ "" """r"""̕"5"ޕ""ҟ"]"t""t""u"V"$"/"t"T* * * + + *  *  * * * *  * + *  *  *  * * *  !*"" !*## $*%% &*'' *(( )*** +*,, -*.. /*00 1*22 3*44 5*66 3*77 3*88 9*:: 9* ;; 9*!<< =*">> =*#?? 9*$@@ 9*%AA *&BB C*'DD E*(FF G*)HH **II *+JJ *,KK L*-MM N*.OO P*/QQ R*0SS T*1UU V*2WW V*3XX Y*4ZZ [*5\\ 9*6]] 9*7^^ 9*8__ `*9aa b*:cc d*;ee f*<gg d*=hh *>ii *?jj 9*@kk 9*All 9*Bmm `*Cnn o*Dpp o*Eqq *Frr E*Gss G*Htt *Iuu *Jvv w*Kxx y*Lzz y*M{{ y*N|| }*O~~ * +P * Q * R * S * T * U * V * W * X * Y * Z * [ * \ * ] * ^ * _ * ` * a * +b 9* c * +d * +e * f * g * h * i * j * k * l * +m -* n * o * p * q * +r /* s * t * u * v * w * x * y * z * { * | * } * ~ *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  $*  *  *  d*  *  *  *  *  *  *  *  *  &*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  C*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  d*  d*  d*  d*  d*  d*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  3*  *  *  *  *  *  *  *  *  *  *  *  G*  *  G*  *  *  *  *  d*  d*  d*  d*  d*  d*  d*  V*  Y*  [*  9*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  d*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  y*  y*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  C*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  d*  d*  d*  d*  *  *  *  *  9*  *  *  *  *  f*  f*  f*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  R*  T*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  )*  )*  *  *  *  *  *  *  *  *  5*  5*  *  d*  d*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  C*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  1*  C*  *  *  G*  *  G*  *  *  *  1*  *  *  *  *  *  *  *  *  *  /*  /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  d*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  C*  9*  *  22samples2count2cpu2 nanoseconds2/usr/local/bin/kube-apiserver2runtime.netpoll2*/usr/local/go/src/runtime/netpoll_epoll.go2runtime.findRunnable2!/usr/local/go/src/runtime/proc.go2runtime.schedule2runtime.park_m2 runtime.mcall2%/usr/local/go/src/runtime/asm_arm64.s2runtime.mapaccess12 /usr/local/go/src/runtime/map.go2&golang.org/x/net/http2.typeFrameParser2&vendor/golang.org/x/net/http2/frame.go2*golang.org/x/net/http2.(*Framer).ReadFrame2?google.golang.org/grpc/internal/transport.(*http2Client).reader2@vendor/google.golang.org/grpc/internal/transport/http2_client.go2runtime.mapaccess1_faststr2(/usr/local/go/src/runtime/map_faststr.go2net/textproto.MIMEHeader.Get2)/usr/local/go/src/net/textproto/header.go2net/http.Header.Get2$/usr/local/go/src/net/http/header.go2*github.com/NYTimes/gziphandler.acceptsGzip2-vendor/github.com/NYTimes/gziphandler/gzip.go2:github.com/NYTimes/gziphandler.GzipHandlerWithOpts.func1.12net/http.HandlerFunc.ServeHTTP2$/usr/local/go/src/net/http/server.go28k8s.io/apiserver/pkg/server/mux.(*pathHandler).ServeHTTP26vendor/k8s.io/apiserver/pkg/server/mux/pathrecorder.go2vendor/github.com/prometheus/client_golang/prometheus/gauge.go2@k8s.io/component-base/metrics.(*GaugeVec).WithLabelValuesChecked2-vendor/k8s.io/component-base/metrics/gauge.go29k8s.io/component-base/metrics.(*GaugeVec).WithLabelValues2=k8s.io/apiserver/pkg/storage/etcd3/metrics.RecordEtcdBookmark2vendor/k8s.io/apiserver/pkg/registry/generic/registry/store.go29k8s.io/apiserver/pkg/endpoints/handlers.GetResource.func125vendor/k8s.io/apiserver/pkg/endpoints/handlers/get.go2@k8s.io/apiserver/pkg/endpoints/handlers.getResourceHandler.func127k8s.io/apiserver/pkg/endpoints.restfulGetResource.func122vendor/k8s.io/apiserver/pkg/endpoints/installer.go2@k8s.io/apiserver/pkg/endpoints/metrics.InstrumentRouteFunc.func128vendor/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go27github.com/emicklei/go-restful/v3.(*Container).dispatch25vendor/github.com/emicklei/go-restful/v3/container.go27github.com/emicklei/go-restful/v3.(*Container).Dispatch2>k8s.io/kube-aggregator/pkg/apiserver.(*proxyHandler).ServeHTTP2k8s.io/apiserver/pkg/endpoints/filters.WithAuthorization.func12>vendor/k8s.io/apiserver/pkg/endpoints/filters/authorization.go2?k8s.io/apiserver/pkg/endpoints/filterlatency.trackStarted.func12Ck8s.io/apiserver/pkg/server/filters.WithPriorityAndFairness.func2.92Cvendor/k8s.io/apiserver/pkg/server/filters/priority-and-fairness.go2Fk8s.io/apiserver/pkg/util/flowcontrol.(*configController).Handle.func22:vendor/k8s.io/apiserver/pkg/util/flowcontrol/apf_filter.go2Rk8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset.(*request).Finish.func12Mvendor/k8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset/queueset.go2Lk8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset.(*request).Finish2@k8s.io/apiserver/pkg/util/flowcontrol.(*configController).Handle2Ak8s.io/apiserver/pkg/server/filters.WithPriorityAndFairness.func22>k8s.io/apiserver/pkg/endpoints/filters.WithImpersonation.func12>vendor/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go2runtime.memmove2)/usr/local/go/src/runtime/memmove_arm64.s27k8s.io/apiserver/pkg/server/filters.withWaitGroup.func127vendor/k8s.io/apiserver/pkg/server/filters/waitgroup.go2@k8s.io/apiserver/pkg/endpoints/filters.WithWarningRecorder.func128vendor/k8s.io/apiserver/pkg/endpoints/filters/warning.go2=k8s.io/apiserver/pkg/endpoints/filters.WithCacheControl.func12=vendor/k8s.io/apiserver/pkg/endpoints/filters/cachecontrol.go25k8s.io/apiserver/pkg/server/httplog.withLogging.func125vendor/k8s.io/apiserver/pkg/server/httplog/httplog.go2@k8s.io/apiserver/pkg/endpoints/filters.WithLatencyTrackers.func12Avendor/k8s.io/apiserver/pkg/endpoints/filters/webhook_duration.go2vendor/google.golang.org/grpc/internal/transport/controlbuf.go2google.golang.org/grpc/internal/transport.newHTTP2Client.func32math/big.mulAddVWW2time.Now2/usr/local/go/src/time/time.go2reflect.unsafe_New2reflect.copyVal2"/usr/local/go/src/reflect/value.go2reflect.(*MapIter).Key2encoding/json.mapEncoder.encode2)/usr/local/go/src/encoding/json/encode.go2"encoding/json.structEncoder.encode2encoding/json.ptrEncoder.encode2)encoding/json.(*encodeState).reflectValue2$encoding/json.(*encodeState).marshal2encoding/json.Marshal2@k8s.io/kube-openapi/pkg/handler3.(*OpenAPIService).getGroupBytes22vendor/k8s.io/kube-openapi/pkg/handler3/handler.go2Bk8s.io/kube-openapi/pkg/handler3.(*OpenAPIService).HandleDiscovery2_k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator.(*Downloader).handlerWithUser.func12Pvendor/k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator/downloader.go2*google.golang.org/grpc/internal/status.New27vendor/google.golang.org/grpc/internal/status/status.go2!google.golang.org/grpc/status.New2.vendor/google.golang.org/grpc/status/status.go2Ggoogle.golang.org/grpc/internal/transport.(*http2Client).operateHeaders2runtime.newproc.func12runtime.systemstack2runtime.newproc24golang.org/x/net/http2.(*serverConn).startFrameWrite27golang.org/x/net/http2.(*serverConn).scheduleFrameWrite2/golang.org/x/net/http2.(*serverConn).writeFrame2*golang.org/x/net/http2.(*serverConn).serve2*golang.org/x/net/http2.(*Server).ServeConn2,golang.org/x/net/http2.ConfigureServer.func12runtime.goexit02runtime.pcvalue2#/usr/local/go/src/runtime/symtab.go2runtime.funcspdelta2time.Time.AppendFormat2 /usr/local/go/src/time/format.go2time.Time.Format2net/http.setLastModified2 /usr/local/go/src/net/http/fs.go2net/http.serveContent2net/http.ServeContent2Wk8s.io/kube-openapi/pkg/handler.(*OpenAPIService).RegisterOpenAPIVersionedService.func121vendor/k8s.io/kube-openapi/pkg/handler/handler.go2runtime.eqslice2"/usr/local/go/src/runtime/mprof.go2runtime.stkbucket2runtime.mProf_Malloc2runtime.profilealloc2runtime.makeslice2"/usr/local/go/src/runtime/slice.go2 path.Join2/usr/local/go/src/path/path.go2;k8s.io/kube-openapi/pkg/handler3.constructServerRelativeURL2lk8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset.(*queueSet).removeTimedOutRequestsFromQueueLocked2qk8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset.(*queueSet).timeoutOldRequestsAndRejectOrEnqueueLocked2Sk8s.io/apiserver/pkg/util/flowcontrol/fairqueuing/queueset.(*queueSet).StartRequest2Fk8s.io/apiserver/pkg/util/flowcontrol.(*configController).startRequest2>vendor/k8s.io/apiserver/pkg/util/flowcontrol/apf_controller.go2Dk8s.io/apimachinery/pkg/apis/meta/v1.(*ManagedFieldsEntry).Unmarshal2;vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.pb.go2k8s.io/apiserver/pkg/endpoints/handlers.UpdateResource.func1.128vendor/k8s.io/apiserver/pkg/endpoints/handlers/update.go2Lk8s.io/apiserver/pkg/registry/rest.(*defaultUpdatedObjectInfo).UpdatedObject23vendor/k8s.io/apiserver/pkg/registry/rest/update.go2Dk8s.io/apiserver/pkg/registry/generic/registry.(*Store).Update.func127k8s.io/apiserver/pkg/storage/etcd3.(*store).updateState2k8s.io/apiserver/pkg/storage/cacher.(*Cacher).GuaranteedUpdate2Uk8s.io/apiserver/pkg/registry/generic/registry.(*DryRunnableStorage).GuaranteedUpdate2>k8s.io/apiserver/pkg/registry/generic/registry.(*Store).Update2>k8s.io/apiserver/pkg/endpoints/handlers.UpdateResource.func1.42>k8s.io/apiserver/pkg/endpoints/handlers.UpdateResource.func1.52Dk8s.io/apiserver/pkg/endpoints/handlers/finisher.finishRequest.func12Cvendor/k8s.io/apiserver/pkg/endpoints/handlers/finisher/finisher.go2+google.golang.org/grpc.(*csAttempt).recvMsg24google.golang.org/grpc.(*clientStream).RecvMsg.func12runtime.epollwait2)k8s.io/client-go/tools/cache.watchHandler20vendor/k8s.io/client-go/tools/cache/reflector.go26k8s.io/client-go/tools/cache.(*Reflector).ListAndWatch2:k8s.io/apiserver/pkg/storage/cacher.(*Cacher).startCaching2?k8s.io/apiserver/pkg/storage/cacher.NewCacherFromConfig.func1.12=k8s.io/apiserver/pkg/storage/cacher.NewCacherFromConfig.func12 sort.Search2;k8s.io/apiserver/pkg/admission/metrics.(*metricSet).observe28vendor/k8s.io/apiserver/pkg/admission/metrics/metrics.go2Uk8s.io/apiserver/pkg/admission/metrics.(*AdmissionMetrics).ObserveAdmissionController2Ek8s.io/apiserver/pkg/admission/metrics.pluginHandlerWithMetrics.Admit2:k8s.io/apiserver/pkg/admission.chainAdmissionHandler.Admit2.vendor/k8s.io/apiserver/pkg/admission/chain.go21k8s.io/apiserver/pkg/admission.(*reinvoker).Admit25vendor/k8s.io/apiserver/pkg/admission/reinvocation.go24k8s.io/apiserver/pkg/admission.(*auditHandler).Admit2.vendor/k8s.io/apiserver/pkg/admission/audit.go2hk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*managedFieldsValidatingAdmissionController).Admit2Hvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/admission.go2>k8s.io/apiserver/pkg/endpoints/handlers.UpdateResource.func1.22golang.org/x/net/http2.(*serverConn).newWriterAndRequestNoBody28golang.org/x/net/http2.(*serverConn).newWriterAndRequest25gopkg.in/square/go-jose.v2/json.(*decodeState).object20vendor/gopkg.in/square/go-jose.v2/json/decode.go24gopkg.in/square/go-jose.v2/json.(*decodeState).value28gopkg.in/square/go-jose.v2/json.(*decodeState).unmarshal2)gopkg.in/square/go-jose.v2/json.Unmarshal25gopkg.in/square/go-jose.v2/jwt.(*JSONWebToken).Claims2,vendor/gopkg.in/square/go-jose.v2/jwt/jwt.go2Ok8s.io/kubernetes/pkg/serviceaccount.(*jwtTokenAuthenticator).AuthenticateToken2pkg/serviceaccount/jwt.go2Zk8s.io/apiserver/pkg/authentication/token/union.(*unionAuthTokenHandler).AuthenticateToken2?vendor/k8s.io/apiserver/pkg/authentication/token/union/union.go2ek8s.io/apiserver/pkg/authentication/token/cache.(*cachedTokenAuthenticator).doAuthenticateToken.func124golang.org/x/sync/singleflight.(*Group).doCall.func225vendor/golang.org/x/sync/singleflight/singleflight.go2.golang.org/x/sync/singleflight.(*Group).doCall2Wk8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator.(*Downloader).OpenAPIV3Root2ek8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator.(*specProxier).updateAPIServiceSpecLocked2Pvendor/k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator/aggregator.go2_k8s.io/kube-aggregator/pkg/controllers/openapiv3/aggregator.(*specProxier).UpdateAPIServiceSpec2Nk8s.io/kube-aggregator/pkg/controllers/openapiv3.(*AggregationController).sync2runtime.usleep2runtime.runqgrab2runtime.runqsteal2;google.golang.org/grpc/balancer/roundrobin.(*rrPicker).Pick2?vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go2?sigs.k8s.io/structured-merge-diff/v4/value.(*freelist).allocate2>vendor/sigs.k8s.io/structured-merge-diff/v4/value/allocator.go2Qsigs.k8s.io/structured-merge-diff/v4/value.(*freelistAllocator).allocValueReflect2Esigs.k8s.io/structured-merge-diff/v4/value.structReflect.IterateUsing2Rsigs.k8s.io/structured-merge-diff/v4/typed.(*validatingObjectWalker).visitMapItems2=vendor/sigs.k8s.io/structured-merge-diff/v4/typed/validate.go2Jsigs.k8s.io/structured-merge-diff/v4/typed.(*validatingObjectWalker).doMap28sigs.k8s.io/structured-merge-diff/v4/typed.resolveSchema2Msigs.k8s.io/structured-merge-diff/v4/typed.(*validatingObjectWalker).validate2>sigs.k8s.io/structured-merge-diff/v4/typed.TypedValue.Validate22sigs.k8s.io/structured-merge-diff/v4/typed.AsTyped2Gsigs.k8s.io/structured-merge-diff/v4/typed.ParseableType.FromStructured2;vendor/sigs.k8s.io/structured-merge-diff/v4/typed/parser.go2Sk8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.(*typeConverter).ObjectToTyped2Lvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/typeconverter.go2runtime.findfunc2 runtime.gfget2runtime.newproc12>k8s.io/apiserver/pkg/endpoints/handlers/finisher.finishRequest2>k8s.io/apiserver/pkg/endpoints/handlers/finisher.FinishRequest227k8s.io/apimachinery/pkg/conversion.(*Converter).Convert26vendor/k8s.io/apimachinery/pkg/conversion/converter.go21k8s.io/apimachinery/pkg/runtime.(*Scheme).Convert20vendor/k8s.io/apimachinery/pkg/runtime/scheme.go20go.etcd.io/etcd/client/v3.(*watchGrpcStream).run2runtime.nanotime12runtime.nanotime2:vendor/golang.org/x/crypto/cryptobyte.(*String).ReadUint162A/usr/local/go/src/vendor/golang.org/x/crypto/cryptobyte/string.go2 runtime.lock22runtime.lockWithRank2 runtime.lock2runtime.sellock2!runtime.(*mcache).prepareForSweep2runtime.acquirep2;go.etcd.io/etcd/client/v3.(*watchGrpcStream).serveSubstream2runtime.(*randomEnum).next2context.WithValue2Agoogle.golang.org/grpc/internal/credentials.NewRequestInfoContext2Avendor/google.golang.org/grpc/internal/credentials/credentials.go2Kgoogle.golang.org/grpc/internal/transport.(*http2Client).createHeaderFields21k8s.io/apiserver/pkg/storage/etcd3.(*store).Count23k8s.io/apiserver/pkg/storage/cacher.(*Cacher).Count2Jk8s.io/apiserver/pkg/registry/generic/registry.(*DryRunnableStorage).Count2Qk8s.io/apiserver/pkg/registry/generic/registry.(*Store).startObservingCount.func12runtime.convTstring28go.etcd.io/etcd/api/v3/etcdserverpb.(*RangeRequest).Size2;go.etcd.io/etcd/api/v3/etcdserverpb.(*RangeRequest).Marshal26google.golang.org/protobuf/internal/impl.legacyMarshal2Avendor/google.golang.org/protobuf/internal/impl/legacy_message.go27google.golang.org/protobuf/proto.MarshalOptions.marshal21vendor/google.golang.org/protobuf/proto/encode.go2=google.golang.org/protobuf/proto.MarshalOptions.MarshalAppend2.github.com/golang/protobuf/proto.marshalAppend2/vendor/github.com/golang/protobuf/proto/wire.go2(github.com/golang/protobuf/proto.Marshal23google.golang.org/grpc/encoding/proto.codec.Marshal25vendor/google.golang.org/grpc/encoding/proto/proto.go2google.golang.org/grpc.encode2)vendor/google.golang.org/grpc/rpc_util.go2!google.golang.org/grpc.prepareMsg2.google.golang.org/grpc.(*clientStream).SendMsg2sync.(*Pool).Get2/usr/local/go/src/sync/pool.go2Ek8s.io/apimachinery/pkg/apis/meta/v1.(*ObjectMeta).SetResourceVersion23vendor/k8s.io/apimachinery/pkg/apis/meta/v1/meta.go2k8s.io/apiserver/pkg/authentication/authenticator.authenticate2hk8s.io/apiserver/pkg/authentication/authenticator.(*audAgnosticRequestAuthenticator).AuthenticateRequest2-github.com/NYTimes/gziphandler.parseEncodings2runtime.slicebytetostring2#/usr/local/go/src/runtime/string.go2strconv.formatBits2!/usr/local/go/src/strconv/itoa.go2strconv.FormatUint2 runtime.add12runtime.newarray2runtime.makeBucketArray2runtime.hashGrow2runtime.mapassign2Ok8s.io/apimachinery/third_party/forked/golang/reflect.Equalities.deepValueEqual2Jvendor/k8s.io/apimachinery/third_party/forked/golang/reflect/deep_equal.go2Jk8s.io/apimachinery/third_party/forked/golang/reflect.Equalities.deepEqual2ck8s.io/apimachinery/third_party/forked/golang/reflect.Equalities.DeepEqualWithNilDifferentFromEmpty2]k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager.IgnoreManagedFieldsTimestampsTransformer2Gvendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/equality.go2runtime.findmoduledatap2Dk8s.io/component-base/metrics.(*GaugeVecWithContext).WithLabelValues2Gk8s.io/apiserver/pkg/authentication/token/cache.statsCollector.blocking2runtime.releaseSudog2Hgoogle.golang.org/grpc/internal/transport.(*recvBufferReader).readClient2Bgoogle.golang.org/grpc/internal/transport.(*recvBufferReader).Read2Agoogle.golang.org/grpc/internal/transport.(*transportReader).Read28google.golang.org/grpc/internal/transport.(*Stream).Read2(google.golang.org/grpc.(*parser).recvMsg2(google.golang.org/grpc.recvAndDecompress2google.golang.org/grpc.recv2 runtime.read2crypto/tls.(*Conn).writeRecord2math/big.basicSqr2math/big.nat.sqrHŻPoZ`p \ No newline at end of file diff --git a/catalogd/pprof/kubeapiserver_heap_profile.pb b/catalogd/pprof/kubeapiserver_heap_profile.pb new file mode 100644 index 0000000000000000000000000000000000000000..94753f97f2f227340541022603bf4f321ef13b78 GIT binary patch literal 560491 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%0Dr2hX;Wx(Xm-=fi7|=xcxPg4Vq9XNYnN{$7T9rU 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%0DU{}$Bo5SK1o)k+%mYwa%bXx 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≧Jz1}f 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
  1. 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�jR@XE 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 literal 0 HcmV?d00001 diff --git a/catalogd/pprof/manager_cpu_profile.pb b/catalogd/pprof/manager_cpu_profile.pb new file mode 100644 index 0000000000000000000000000000000000000000..ae48d4a4bab8b2ca799d5893a881d9893e3e8ef4 GIT binary patch literal 3387 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 F{vQojR*e7v literal 0 HcmV?d00001 diff --git a/catalogd/scripts/install.tpl.sh b/catalogd/scripts/install.tpl.sh new file mode 100644 index 000000000..b71892439 --- /dev/null +++ b/catalogd/scripts/install.tpl.sh @@ -0,0 +1,45 @@ +#!/bin/bash +set -euo pipefail +IFS=$'\n\t' + +catalogd_manifest=$MANIFEST + +if [[ -z "$catalogd_manifest" ]]; then + echo "Error: Missing required MANIFEST variable" + exit 1 +fi + +cert_mgr_version=$CERT_MGR_VERSION +default_catalogs=$DEFAULT_CATALOGS + +if [[ -z "$default_catalogs" || -z "$cert_mgr_version" ]]; then + err="Error: Missing component value(s) for: " + if [[ -z "$default_catalogs" ]]; then + err+="default cluster catalogs " + fi + if [[ -z "$cert_mgr_version" ]]; then + err+="cert-manager version " + fi + echo "$err" + exit 1 +fi + +function kubectl_wait() { + namespace=$1 + runtime=$2 + timeout=$3 + + kubectl wait --for=condition=Available --namespace="${namespace}" "${runtime}" --timeout="${timeout}" +} + +kubectl apply -f "https://github.com/cert-manager/cert-manager/releases/download/${cert_mgr_version}/cert-manager.yaml" +kubectl_wait "cert-manager" "deployment/cert-manager-cainjector" "60s" +kubectl_wait "cert-manager" "deployment/cert-manager-webhook" "60s" +kubectl_wait "cert-manager" "deployment/cert-manager" "60s" +kubectl wait mutatingwebhookconfigurations/cert-manager-webhook --for=jsonpath='{.webhooks[0].clientConfig.caBundle}' --timeout=60s +kubectl wait validatingwebhookconfigurations/cert-manager-webhook --for=jsonpath='{.webhooks[0].clientConfig.caBundle}' --timeout=60s +kubectl apply -f "${catalogd_manifest}" +kubectl_wait "olmv1-system" "deployment/catalogd-controller-manager" "60s" + +kubectl apply -f "${default_catalogs}" +kubectl wait --for=condition=Serving "clustercatalog/operatorhubio" --timeout="60s" \ No newline at end of file diff --git a/catalogd/test/e2e/e2e_suite_test.go b/catalogd/test/e2e/e2e_suite_test.go new file mode 100644 index 000000000..0a8970a1f --- /dev/null +++ b/catalogd/test/e2e/e2e_suite_test.go @@ -0,0 +1,49 @@ +package e2e + +import ( + "fmt" + "os" + "testing" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" +) + +var ( + cfg *rest.Config + c client.Client + err error + kubeClient kubernetes.Interface +) + +func TestE2E(t *testing.T) { + _, err := ctrl.GetConfig() + if err != nil { + fmt.Println("Error: Could not get current Kubernetes context. Verify the cluster configuration") + os.Exit(0) + } + RegisterFailHandler(Fail) + SetDefaultEventuallyTimeout(1 * time.Minute) + SetDefaultEventuallyPollingInterval(1 * time.Second) + RunSpecs(t, "E2E Suite") +} + +var _ = BeforeSuite(func() { + cfg = ctrl.GetConfigOrDie() + + sch := scheme.Scheme + Expect(catalogdv1.AddToScheme(sch)).To(Succeed()) + c, err = client.New(cfg, client.Options{Scheme: sch}) + Expect(err).To(Not(HaveOccurred())) + kubeClient, err = kubernetes.NewForConfig(cfg) + Expect(err).ToNot(HaveOccurred()) +}) diff --git a/catalogd/test/e2e/metrics_endpoint_test.go b/catalogd/test/e2e/metrics_endpoint_test.go new file mode 100644 index 000000000..803ffaf28 --- /dev/null +++ b/catalogd/test/e2e/metrics_endpoint_test.go @@ -0,0 +1,127 @@ +package e2e + +import ( + "bytes" + "io" + "os/exec" + "testing" + + "github.com/stretchr/testify/require" +) + +// nolint:gosec +// TestCatalogdMetricsExportedEndpoint verifies that the metrics endpoint for the catalogd +// is exported correctly and accessible by authorized users through RBAC and a ServiceAccount token. +// The test performs the following steps: +// 1. Creates a ClusterRoleBinding to grant necessary permissions for accessing metrics. +// 2. Generates a ServiceAccount token for authentication. +// 3. Deploys a curl pod to interact with the metrics endpoint. +// 4. Waits for the curl pod to become ready. +// 5. Executes a curl command from the pod to validate the metrics endpoint. +// 6. Cleans up all resources created during the test, such as the ClusterRoleBinding and curl pod. +func TestCatalogdMetricsExportedEndpoint(t *testing.T) { + var ( + token string + curlPod = "curl-metrics" + client = "" + clients = []string{"kubectl", "oc"} + ) + + t.Log("Looking for k8s client") + for _, c := range clients { + // Would prefer to use `command -v`, but even that may not be installed! + err := exec.Command(c, "version", "--client").Run() + if err == nil { + client = c + break + } + } + if client == "" { + t.Fatal("k8s client not found") + } + t.Logf("Using %q as k8s client", client) + + t.Log("Determining catalogd namespace") + cmd := exec.Command(client, "get", "pods", "--all-namespaces", "--selector=control-plane=catalogd-controller-manager", "--output=jsonpath={.items[0].metadata.namespace}") + output, err := cmd.CombinedOutput() + require.NoError(t, err, "Error creating determining catalogd namespace: %s", string(output)) + namespace := string(output) + if namespace == "" { + t.Fatal("No catalogd namespace found") + } + t.Logf("Using %q as catalogd namespace", namespace) + + t.Log("Creating ClusterRoleBinding for metrics access") + cmd = exec.Command(client, "create", "clusterrolebinding", "catalogd-metrics-binding", + "--clusterrole=catalogd-metrics-reader", + "--serviceaccount="+namespace+":catalogd-controller-manager") + output, err = cmd.CombinedOutput() + require.NoError(t, err, "Error creating ClusterRoleBinding: %s", string(output)) + + defer func() { + t.Log("Cleaning up ClusterRoleBinding") + _ = exec.Command(client, "delete", "clusterrolebinding", "catalogd-metrics-binding", "--ignore-not-found=true").Run() + }() + + t.Log("Creating service account token for authentication") + tokenCmd := exec.Command(client, "create", "token", "catalogd-controller-manager", "-n", namespace) + tokenOutput, tokenCombinedOutput, err := stdoutAndCombined(tokenCmd) + require.NoError(t, err, "Error creating token: %s", string(tokenCombinedOutput)) + token = string(bytes.TrimSpace(tokenOutput)) + + t.Log("Creating a pod to run curl commands") + cmd = exec.Command(client, "run", curlPod, + "--image=curlimages/curl:7.87.0", "-n", namespace, + "--restart=Never", + "--overrides", `{ + "spec": { + "containers": [{ + "name": "curl", + "image": "curlimages/curl:7.87.0", + "command": ["sh", "-c", "sleep 3600"], + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": ["ALL"] + }, + "runAsNonRoot": true, + "runAsUser": 1000, + "seccompProfile": { + "type": "RuntimeDefault" + } + } + }], + "serviceAccountName": "catalogd-controller-manager" + } + }`) + output, err = cmd.CombinedOutput() + require.NoError(t, err, "Error creating curl pod: %s", string(output)) + + defer func() { + t.Log("Cleaning up curl pod") + _ = exec.Command(client, "delete", "pod", curlPod, "-n", namespace, "--ignore-not-found=true").Run() + }() + + t.Log("Waiting for the curl pod to become ready") + waitCmd := exec.Command(client, "wait", "--for=condition=Ready", "pod", curlPod, "-n", namespace, "--timeout=60s") + waitOutput, waitErr := waitCmd.CombinedOutput() + require.NoError(t, waitErr, "Error waiting for curl pod to be ready: %s", string(waitOutput)) + + t.Log("Validating the metrics endpoint") + metricsURL := "https://catalogd-service.olmv1-system.svc.cluster.local:7443/metrics" + curlCmd := exec.Command(client, "exec", curlPod, "-n", namespace, "--", + "curl", "-v", "-k", "-H", "Authorization: Bearer "+token, metricsURL) + output, err = curlCmd.CombinedOutput() + require.NoError(t, err, "Error calling metrics endpoint: %s", string(output)) + require.Contains(t, string(output), "200 OK", "Metrics endpoint did not return 200 OK") +} + +func stdoutAndCombined(cmd *exec.Cmd) ([]byte, []byte, error) { + var outOnly bytes.Buffer + var outAndErr bytes.Buffer + allWriter := io.MultiWriter(&outOnly, &outAndErr) + cmd.Stderr = &outAndErr + cmd.Stdout = allWriter + err := cmd.Run() + return outOnly.Bytes(), outAndErr.Bytes(), err +} diff --git a/catalogd/test/e2e/unpack_test.go b/catalogd/test/e2e/unpack_test.go new file mode 100644 index 000000000..a00200703 --- /dev/null +++ b/catalogd/test/e2e/unpack_test.go @@ -0,0 +1,109 @@ +package e2e + +import ( + "context" + "os" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/google/go-cmp/cmp" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" +) + +const ( + catalogRefEnvVar = "TEST_CATALOG_IMAGE" + catalogName = "test-catalog" + pkg = "prometheus" + version = "0.47.0" + channel = "beta" + bundle = "prometheus-operator.0.47.0" + bundleImage = "localhost/testdata/bundles/registry-v1/prometheus-operator:v0.47.0" +) + +// catalogImageRef returns the image reference for the test catalog image, defaulting to the value of the environment +// variable TEST_CATALOG_IMAGE if set, falling back to docker-registry.catalogd-e2e.svc:5000/test-catalog:e2e otherwise. +func catalogImageRef() string { + if s := os.Getenv(catalogRefEnvVar); s != "" { + return s + } + + return "docker-registry.catalogd-e2e.svc:5000/test-catalog:e2e" +} + +var _ = Describe("ClusterCatalog Unpacking", func() { + var ( + ctx context.Context + catalog *catalogdv1.ClusterCatalog + ) + When("A ClusterCatalog is created", func() { + BeforeEach(func() { + ctx = context.Background() + var err error + + catalog = &catalogdv1.ClusterCatalog{ + ObjectMeta: metav1.ObjectMeta{ + Name: catalogName, + }, + Spec: catalogdv1.ClusterCatalogSpec{ + Source: catalogdv1.CatalogSource{ + Type: catalogdv1.SourceTypeImage, + Image: &catalogdv1.ImageSource{ + Ref: catalogImageRef(), + }, + }, + }, + } + + err = c.Create(ctx, catalog) + Expect(err).ToNot(HaveOccurred()) + }) + + It("Successfully unpacks catalog contents", func() { + By("Ensuring ClusterCatalog has Status.Condition of Progressing with a status == False and reason == Succeeded") + Eventually(func(g Gomega) { + err := c.Get(ctx, types.NamespacedName{Name: catalog.Name}, catalog) + g.Expect(err).ToNot(HaveOccurred()) + cond := meta.FindStatusCondition(catalog.Status.Conditions, catalogdv1.TypeProgressing) + g.Expect(cond).ToNot(BeNil()) + g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) + g.Expect(cond.Reason).To(Equal(catalogdv1.ReasonSucceeded)) + }).Should(Succeed()) + + By("Checking that it has an appropriate name label") + Expect(catalog.ObjectMeta.Labels).To(Not(BeNil())) + Expect(catalog.ObjectMeta.Labels).To(Not(BeEmpty())) + Expect(catalog.ObjectMeta.Labels).To(HaveKeyWithValue("olm.operatorframework.io/metadata.name", catalogName)) + + By("Making sure the catalog content is available via the http server") + actualFBC, err := ReadTestCatalogServerContents(ctx, catalog, c, kubeClient) + Expect(err).To(Not(HaveOccurred())) + + expectedFBC, err := os.ReadFile("../../testdata/catalogs/test-catalog/expected_all.json") + Expect(err).To(Not(HaveOccurred())) + Expect(cmp.Diff(expectedFBC, actualFBC)).To(BeEmpty()) + + By("Ensuring ClusterCatalog has Status.Condition of Type = Serving with a status == True") + Eventually(func(g Gomega) { + err := c.Get(ctx, types.NamespacedName{Name: catalog.Name}, catalog) + g.Expect(err).ToNot(HaveOccurred()) + cond := meta.FindStatusCondition(catalog.Status.Conditions, catalogdv1.TypeServing) + g.Expect(cond).ToNot(BeNil()) + g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) + g.Expect(cond.Reason).To(Equal(catalogdv1.ReasonAvailable)) + }).Should(Succeed()) + }) + AfterEach(func() { + Expect(c.Delete(ctx, catalog)).To(Succeed()) + Eventually(func(g Gomega) { + err = c.Get(ctx, types.NamespacedName{Name: catalog.Name}, &catalogdv1.ClusterCatalog{}) + g.Expect(errors.IsNotFound(err)).To(BeTrue()) + }).Should(Succeed()) + }) + }) +}) diff --git a/catalogd/test/e2e/util.go b/catalogd/test/e2e/util.go new file mode 100644 index 000000000..dab5edaeb --- /dev/null +++ b/catalogd/test/e2e/util.go @@ -0,0 +1,51 @@ +package e2e + +import ( + "context" + "fmt" + "io" + "net/url" + "strings" + + "k8s.io/client-go/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/client" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" +) + +func ReadTestCatalogServerContents(ctx context.Context, catalog *catalogdv1.ClusterCatalog, c client.Client, kubeClient kubernetes.Interface) ([]byte, error) { + if catalog == nil { + return nil, fmt.Errorf("cannot read nil catalog") + } + if catalog.Status.URLs == nil { + return nil, fmt.Errorf("catalog %q has no catalog urls", catalog.Name) + } + url, err := url.Parse(catalog.Status.URLs.Base) + if err != nil { + return nil, fmt.Errorf("error parsing clustercatalog url %q: %v", catalog.Status.URLs.Base, err) + } + // url is expected to be in the format of + // http://{service_name}.{namespace}.svc/catalogs/{catalog_name}/ + // so to get the namespace and name of the service we grab only + // the hostname and split it on the '.' character + ns := strings.Split(url.Hostname(), ".")[1] + name := strings.Split(url.Hostname(), ".")[0] + port := url.Port() + // the ProxyGet() call below needs an explicit port value, so if + // value from url.Port() is empty, we assume port 443. + if port == "" { + if url.Scheme == "https" { + port = "443" + } else { + port = "80" + } + } + resp := kubeClient.CoreV1().Services(ns).ProxyGet(url.Scheme, name, port, url.JoinPath("api", "v1", "all").Path, map[string]string{}) + rc, err := resp.Stream(ctx) + if err != nil { + return nil, err + } + defer rc.Close() + + return io.ReadAll(rc) +} diff --git a/catalogd/test/tools/imageregistry/imagebuilder.yaml b/catalogd/test/tools/imageregistry/imagebuilder.yaml new file mode 100644 index 000000000..a9035ccdd --- /dev/null +++ b/catalogd/test/tools/imageregistry/imagebuilder.yaml @@ -0,0 +1,32 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: kaniko + namespace: catalogd-e2e +spec: + template: + spec: + containers: + - name: kaniko + image: gcr.io/kaniko-project/executor:latest + args: ["--dockerfile=/workspace/test-catalog.Dockerfile", + "--context=/workspace/", + "--destination=docker-registry.catalogd-e2e.svc:5000/test-catalog:e2e", + "--skip-tls-verify"] + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - name: dockerfile + mountPath: /workspace/ + - name: build-contents + mountPath: /workspace/test-catalog/ + restartPolicy: Never + volumes: + - name: dockerfile + configMap: + name: catalogd-e2e.dockerfile + items: + - key: test-catalog.Dockerfile + path: test-catalog.Dockerfile + - name: build-contents + configMap: + name: catalogd-e2e.build-contents diff --git a/catalogd/test/tools/imageregistry/imgreg.yaml b/catalogd/test/tools/imageregistry/imgreg.yaml new file mode 100644 index 000000000..c8a104351 --- /dev/null +++ b/catalogd/test/tools/imageregistry/imgreg.yaml @@ -0,0 +1,75 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: catalogd-e2e +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned-issuer + namespace: catalogd-e2e +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: catalogd-e2e-registry + namespace: catalogd-e2e +spec: + secretName: catalogd-e2e-registry + isCA: true + dnsNames: + - docker-registry.catalogd-e2e.svc + privateKey: + algorithm: ECDSA + size: 256 + issuerRef: + name: ${ISSUER_NAME} + kind: ${ISSUER_KIND} + group: cert-manager.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: docker-registry + namespace: catalogd-e2e + labels: + app: registry +spec: + replicas: 1 + selector: + matchLabels: + app: registry + template: + metadata: + labels: + app: registry + spec: + containers: + - name: registry + image: registry:2 + volumeMounts: + - name: certs-vol + mountPath: "/certs" + env: + - name: REGISTRY_HTTP_TLS_CERTIFICATE + value: "/certs/tls.crt" + - name: REGISTRY_HTTP_TLS_KEY + value: "/certs/tls.key" + volumes: + - name: certs-vol + secret: + secretName: catalogd-e2e-registry +--- +apiVersion: v1 +kind: Service +metadata: + name: docker-registry + namespace: catalogd-e2e +spec: + selector: + app: registry + ports: + - port: 5000 + targetPort: 5000 diff --git a/catalogd/test/tools/imageregistry/pre-upgrade-setup.sh b/catalogd/test/tools/imageregistry/pre-upgrade-setup.sh new file mode 100755 index 000000000..707e2c9e6 --- /dev/null +++ b/catalogd/test/tools/imageregistry/pre-upgrade-setup.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +set -euo pipefail + + +help="pre-upgrade-setup.sh is used to create some basic resources +which will later be used in upgrade testing. + +Usage: + pre-upgrade-setup.sh [TEST_CLUSTER_CATALOG_IMAGE] [TEST_CLUSTER_CATALOG_NAME] +" + +if [[ "$#" -ne 2 ]]; then + echo "Illegal number of arguments passed" + echo "${help}" + exit 1 +fi + +export TEST_CLUSTER_CATALOG_IMAGE=$1 +export TEST_CLUSTER_CATALOG_NAME=$2 + +kubectl apply -f - << EOF +apiVersion: olm.operatorframework.io/v1 +kind: ClusterCatalog +metadata: + name: ${TEST_CLUSTER_CATALOG_NAME} +spec: + source: + type: Image + image: + ref: ${TEST_CLUSTER_CATALOG_IMAGE} +EOF + +kubectl wait --for=condition=Serving --timeout=60s ClusterCatalog "$TEST_CLUSTER_CATALOG_NAME" diff --git a/catalogd/test/tools/imageregistry/registry.sh b/catalogd/test/tools/imageregistry/registry.sh new file mode 100755 index 000000000..3995c9b3f --- /dev/null +++ b/catalogd/test/tools/imageregistry/registry.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -e + +# registry.sh will create an in-cluster image registry useful for end-to-end testing +# of catalogd's unpacking process. It does a few things: +# 1. Installs cert-manager for creating a self-signed certificate for the image registry +# 2. Creates all the resources necessary for deploying the image registry in the catalogd-e2e namespace +# 3. Creates ConfigMaps containing the test catalog + Dockerfile to be mounted to the kaniko pod +# 4. Waits for kaniko pod to have Condition Complete == true, indicating the test catalog image has been built + pushed +# to the test image registry +# Usage: +# registry.sh + +if [[ "$#" -ne 2 ]]; then + echo "Incorrect number of arguments passed" + echo "Usage: registry.sh " + exit 1 +fi + +export ISSUER_KIND=$1 +export ISSUER_NAME=$2 + +# create the image registry with all the certs +envsubst '${ISSUER_KIND},${ISSUER_NAME}' < test/tools/imageregistry/imgreg.yaml | kubectl apply -f - +kubectl wait -n catalogd-e2e --for=condition=Available deployment/docker-registry --timeout=60s + +# Load the testdata onto the cluster as a configmap so it can be used with kaniko +kubectl create configmap -n catalogd-e2e --from-file=testdata/catalogs/test-catalog.Dockerfile catalogd-e2e.dockerfile +kubectl create configmap -n catalogd-e2e --from-file=testdata/catalogs/test-catalog catalogd-e2e.build-contents + +# Create the kaniko pod to build the test image and push it to the test registry. +kubectl apply -f test/tools/imageregistry/imagebuilder.yaml +kubectl wait --for=condition=Complete -n catalogd-e2e jobs/kaniko --timeout=60s diff --git a/catalogd/test/upgrade/unpack_test.go b/catalogd/test/upgrade/unpack_test.go new file mode 100644 index 000000000..e13354454 --- /dev/null +++ b/catalogd/test/upgrade/unpack_test.go @@ -0,0 +1,131 @@ +package upgradee2e + +import ( + "bufio" + "context" + "fmt" + "os" + "strings" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/google/go-cmp/cmp" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" + "github.com/operator-framework/operator-controller/catalogd/test/e2e" +) + +var _ = Describe("ClusterCatalog Unpacking", func() { + When("A ClusterCatalog is created", func() { + It("Successfully unpacks catalog contents", func() { + ctx := context.Background() + + var managerDeployment appsv1.Deployment + managerLabelSelector := labels.Set{"control-plane": "catalogd-controller-manager"} + By("Checking that the controller-manager deployment is updated") + Eventually(func(g Gomega) { + var managerDeployments appsv1.DeploymentList + err := c.List(ctx, &managerDeployments, client.MatchingLabels(managerLabelSelector), client.InNamespace("olmv1-system")) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(managerDeployments.Items).To(HaveLen(1)) + managerDeployment = managerDeployments.Items[0] + g.Expect(managerDeployment.Status.UpdatedReplicas).To(Equal(*managerDeployment.Spec.Replicas)) + g.Expect(managerDeployment.Status.Replicas).To(Equal(*managerDeployment.Spec.Replicas)) + g.Expect(managerDeployment.Status.AvailableReplicas).To(Equal(*managerDeployment.Spec.Replicas)) + g.Expect(managerDeployment.Status.ReadyReplicas).To(Equal(*managerDeployment.Spec.Replicas)) + }).Should(Succeed()) + + var managerPod corev1.Pod + By("Waiting for only one controller-manager pod to remain") + Eventually(func(g Gomega) { + var managerPods corev1.PodList + err := c.List(ctx, &managerPods, client.MatchingLabels(managerLabelSelector)) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(managerPods.Items).To(HaveLen(1)) + managerPod = managerPods.Items[0] + }).Should(Succeed()) + + By("Reading logs to make sure that ClusterCatalog was reconciled by catalogdv1") + logCtx, cancel := context.WithTimeout(ctx, time.Minute) + defer cancel() + substrings := []string{ + "reconcile ending", + fmt.Sprintf(`ClusterCatalog=%q`, testClusterCatalogName), + } + found, err := watchPodLogsForSubstring(logCtx, &managerPod, "manager", substrings...) + Expect(err).ToNot(HaveOccurred()) + Expect(found).To(BeTrue()) + + catalog := &catalogdv1.ClusterCatalog{} + By("Ensuring ClusterCatalog has Status.Condition of Progressing with a status == True, reason == Succeeded") + Eventually(func(g Gomega) { + err := c.Get(ctx, types.NamespacedName{Name: testClusterCatalogName}, catalog) + g.Expect(err).ToNot(HaveOccurred()) + cond := meta.FindStatusCondition(catalog.Status.Conditions, catalogdv1.TypeProgressing) + g.Expect(cond).ToNot(BeNil()) + g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) + g.Expect(cond.Reason).To(Equal(catalogdv1.ReasonSucceeded)) + }).Should(Succeed()) + + expectedFBC, err := os.ReadFile("../../testdata/catalogs/test-catalog/expected_all.json") + Expect(err).To(Not(HaveOccurred())) + + By("Making sure the catalog content is available via the http server") + Eventually(func(g Gomega) { + actualFBC, err := e2e.ReadTestCatalogServerContents(ctx, catalog, c, kubeClient) + g.Expect(err).To(Not(HaveOccurred())) + g.Expect(cmp.Diff(expectedFBC, actualFBC)).To(BeEmpty()) + }).Should(Succeed()) + + By("Ensuring ClusterCatalog has Status.Condition of Serving with a status == True, reason == Available") + Eventually(func(g Gomega) { + err := c.Get(ctx, types.NamespacedName{Name: testClusterCatalogName}, catalog) + g.Expect(err).ToNot(HaveOccurred()) + cond := meta.FindStatusCondition(catalog.Status.Conditions, catalogdv1.TypeServing) + g.Expect(cond).ToNot(BeNil()) + g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) + g.Expect(cond.Reason).To(Equal(catalogdv1.ReasonAvailable)) + }).Should(Succeed()) + }) + }) +}) + +func watchPodLogsForSubstring(ctx context.Context, pod *corev1.Pod, container string, substrings ...string) (bool, error) { + podLogOpts := corev1.PodLogOptions{ + Follow: true, + Container: container, + } + + req := kubeClient.CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, &podLogOpts) + podLogs, err := req.Stream(ctx) + if err != nil { + return false, err + } + defer podLogs.Close() + + scanner := bufio.NewScanner(podLogs) + for scanner.Scan() { + line := scanner.Text() + + foundCount := 0 + for _, substring := range substrings { + if strings.Contains(line, substring) { + foundCount++ + } + } + if foundCount == len(substrings) { + return true, nil + } + } + + return false, scanner.Err() +} diff --git a/catalogd/test/upgrade/upgrade_suite_test.go b/catalogd/test/upgrade/upgrade_suite_test.go new file mode 100644 index 000000000..33b7c731b --- /dev/null +++ b/catalogd/test/upgrade/upgrade_suite_test.go @@ -0,0 +1,53 @@ +package upgradee2e + +import ( + "os" + "testing" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + catalogdv1 "github.com/operator-framework/operator-controller/catalogd/api/v1" +) + +const ( + testClusterCatalogNameEnv = "TEST_CLUSTER_CATALOG_NAME" +) + +var ( + cfg *rest.Config + c client.Client + err error + kubeClient kubernetes.Interface + + testClusterCatalogName string +) + +func TestUpgradeE2E(t *testing.T) { + RegisterFailHandler(Fail) + SetDefaultEventuallyTimeout(1 * time.Minute) + SetDefaultEventuallyPollingInterval(1 * time.Second) + RunSpecs(t, "Upgrade E2E Suite") +} + +var _ = BeforeSuite(func() { + cfg = ctrl.GetConfigOrDie() + + sch := scheme.Scheme + Expect(catalogdv1.AddToScheme(sch)).To(Succeed()) + c, err = client.New(cfg, client.Options{Scheme: sch}) + Expect(err).To(Not(HaveOccurred())) + kubeClient, err = kubernetes.NewForConfig(cfg) + Expect(err).ToNot(HaveOccurred()) + + var ok bool + testClusterCatalogName, ok = os.LookupEnv(testClusterCatalogNameEnv) + Expect(ok).To(BeTrue()) +}) diff --git a/catalogd/testdata/catalogs/test-catalog.Dockerfile b/catalogd/testdata/catalogs/test-catalog.Dockerfile new file mode 100644 index 000000000..849d331bd --- /dev/null +++ b/catalogd/testdata/catalogs/test-catalog.Dockerfile @@ -0,0 +1,6 @@ +FROM scratch +COPY test-catalog /configs + +# Set DC-specific label for the location of the DC root directory +# in the image +LABEL operators.operatorframework.io.index.configs.v1=/configs \ No newline at end of file diff --git a/catalogd/testdata/catalogs/test-catalog/.indexignore b/catalogd/testdata/catalogs/test-catalog/.indexignore new file mode 100644 index 000000000..699fa6d33 --- /dev/null +++ b/catalogd/testdata/catalogs/test-catalog/.indexignore @@ -0,0 +1,2 @@ +/expected_all.json +..* diff --git a/catalogd/testdata/catalogs/test-catalog/catalog.yaml b/catalogd/testdata/catalogs/test-catalog/catalog.yaml new file mode 100644 index 000000000..14d33b9d9 --- /dev/null +++ b/catalogd/testdata/catalogs/test-catalog/catalog.yaml @@ -0,0 +1,20 @@ +--- +schema: olm.package +name: prometheus +defaultChannel: beta +--- +schema: olm.channel +name: beta +package: prometheus +entries: + - name: prometheus-operator.0.47.0 +--- +schema: olm.bundle +name: prometheus-operator.0.47.0 +package: prometheus +image: localhost/testdata/bundles/registry-v1/prometheus-operator:v0.47.0 +properties: + - type: olm.package + value: + packageName: prometheus + version: 0.47.0 diff --git a/catalogd/testdata/catalogs/test-catalog/expected_all.json b/catalogd/testdata/catalogs/test-catalog/expected_all.json new file mode 100644 index 000000000..554488982 --- /dev/null +++ b/catalogd/testdata/catalogs/test-catalog/expected_all.json @@ -0,0 +1,3 @@ +{"defaultChannel":"beta","name":"prometheus","schema":"olm.package"} +{"entries":[{"name":"prometheus-operator.0.47.0"}],"name":"beta","package":"prometheus","schema":"olm.channel"} +{"image":"localhost/testdata/bundles/registry-v1/prometheus-operator:v0.47.0","name":"prometheus-operator.0.47.0","package":"prometheus","properties":[{"type":"olm.package","value":{"packageName":"prometheus","version":"0.47.0"}}],"schema":"olm.bundle"} diff --git a/cmd/manager/main.go b/cmd/operator-controller/main.go similarity index 99% rename from cmd/manager/main.go rename to cmd/operator-controller/main.go index 8bb230895..345560bcd 100644 --- a/cmd/manager/main.go +++ b/cmd/operator-controller/main.go @@ -49,10 +49,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/metrics/filters" "sigs.k8s.io/controller-runtime/pkg/metrics/server" - catalogd "github.com/operator-framework/catalogd/api/v1" helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client" ocv1 "github.com/operator-framework/operator-controller/api/v1" + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" "github.com/operator-framework/operator-controller/internal/action" "github.com/operator-framework/operator-controller/internal/applier" "github.com/operator-framework/operator-controller/internal/authentication" diff --git a/config/base/manager/manager.yaml b/config/base/manager/manager.yaml index 12bd673a0..25ba5598a 100644 --- a/config/base/manager/manager.yaml +++ b/config/base/manager/manager.yaml @@ -49,7 +49,7 @@ spec: type: RuntimeDefault containers: - command: - - /manager + - /operator-controller args: - "--health-probe-bind-address=:8081" - "--metrics-bind-address=:8443" diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml new file mode 100644 index 000000000..a5842de42 --- /dev/null +++ b/config/webhook/manifests.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-olm-operatorframework-io-v1-clustercatalog + failurePolicy: Fail + name: inject-metadata-name.olm.operatorframework.io + rules: + - apiGroups: + - olm.operatorframework.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - clustercatalogs + sideEffects: None + timeoutSeconds: 10 diff --git a/docs/contribute/developer.md b/docs/contribute/developer.md index f21a3b28b..a87f3a682 100644 --- a/docs/contribute/developer.md +++ b/docs/contribute/developer.md @@ -91,16 +91,6 @@ Follow Tilt's [instructions](https://docs.tilt.dev/install.html) for installatio operator-controller requires [catalogd](https://github.com/operator-framework/catalogd). Please make sure it's installed, either normally or via its own Tiltfile., before proceeding. If you want to use Tilt, make sure you specify a unique `--port` flag to each `tilt up` invocation. -### Install tilt-support Repo - -You must install the tilt-support repo at the directory level above this repo: - -```bash -pushd .. -git clone https://github.com/operator-framework/tilt-support -popd -``` - ### Starting Tilt This is typically as short as: @@ -136,6 +126,15 @@ v0.33.1, built 2023-06-28 At the end of the installation process, the command output will prompt you to press the space bar to open the web UI, which provides a useful overview of all the installed components. +Shortly after starting, Tilt processes the `Tiltfile`, resulting in: + +- Building the go binaries +- Building the images +- Loading the images into kind +- Running kustomize and applying everything except the Deployments that reference the images above +- Modifying the Deployments to use the just-built images +- Creating the Deployments + --- ## Special Setup for MacOS @@ -161,6 +160,14 @@ done --- +## Making code changes + +Any time you change any of the files listed in the `deps` section in the `_binary` `local_resource`, +Tilt automatically rebuilds the go binary. As soon as the binary is rebuilt, Tilt pushes it (and only it) into the +appropriate running container, and then restarts the process. + +--- + ## Contributing Refer to [CONTRIBUTING.md](contributing.md) for more information. diff --git a/go.mod b/go.mod index 1c961e3b1..ab72212f1 100644 --- a/go.mod +++ b/go.mod @@ -13,11 +13,14 @@ require ( github.com/go-logr/logr v1.4.2 github.com/google/go-cmp v0.6.0 github.com/google/go-containerregistry v0.20.2 + github.com/klauspost/compress v1.17.11 + github.com/onsi/ginkgo/v2 v2.22.1 + github.com/onsi/gomega v1.36.2 github.com/opencontainers/go-digest v1.0.0 github.com/operator-framework/api v0.27.0 - github.com/operator-framework/catalogd v1.1.0 github.com/operator-framework/helm-operator-plugins v0.7.0 github.com/operator-framework/operator-registry v1.48.0 + github.com/prometheus/client_golang v1.20.5 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.10.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 @@ -26,6 +29,7 @@ require ( k8s.io/api v0.31.4 k8s.io/apiextensions-apiserver v0.31.4 k8s.io/apimachinery v0.31.4 + k8s.io/apiserver v0.31.4 k8s.io/cli-runtime v0.31.4 k8s.io/client-go v0.31.4 k8s.io/component-base v0.31.4 @@ -105,6 +109,7 @@ require ( github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-openapi/validate v0.24.0 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -113,6 +118,7 @@ require ( github.com/google/cel-go v0.20.1 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.1 // indirect @@ -135,7 +141,6 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368 // indirect github.com/k14s/ytt v0.36.0 // indirect - github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect @@ -166,7 +171,6 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/oklog/ulid v1.3.1 // indirect - github.com/onsi/gomega v1.36.2 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11 // indirect @@ -176,7 +180,6 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/proglottis/gpgme v0.1.3 // indirect - github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -227,6 +230,7 @@ require ( golang.org/x/term v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.28.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect @@ -237,7 +241,6 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiserver v0.31.4 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/kubectl v0.31.3 // indirect oras.land/oras-go v1.2.5 // indirect diff --git a/go.sum b/go.sum index 8fc9c1882..b7283b9fe 100644 --- a/go.sum +++ b/go.sum @@ -518,8 +518,8 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= -github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= +github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM= +github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -535,8 +535,6 @@ github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11 h1:eT github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11/go.mod h1:EmVJt97N+pfWFsli/ipXTBZqSG5F5KGQhm3c3IsGq1o= github.com/operator-framework/api v0.27.0 h1:OrVaGKZJvbZo58HTv2guz7aURkhVKYhFqZ/6VpifiXI= github.com/operator-framework/api v0.27.0/go.mod h1:lg2Xx+S8NQWGYlEOvFwQvH46E5EK5IrAIL7HWfAhciM= -github.com/operator-framework/catalogd v1.1.0 h1:mu2DYL5mpREEAAP+uPG+CMSsfsJkgrIasgLRG8nvwJg= -github.com/operator-framework/catalogd v1.1.0/go.mod h1:8Je9CqMPwhNgRoqGX5OPsLYHsEoTDvPnELLLKRw1RHE= github.com/operator-framework/helm-operator-plugins v0.7.0 h1:YmtIWFc9BaNaDc5mk/dkG0P2BqPZOqpDvjWih5Fczuk= github.com/operator-framework/helm-operator-plugins v0.7.0/go.mod h1:fUUCJR3bWtMBZ1qdDhbwjacsBHi9uT576tF4u/DwOgQ= github.com/operator-framework/operator-lib v0.15.0 h1:0QeRM4PMtThqINpcFGCEBnIV3Z8u7/8fYLEx6mUtdcM= @@ -787,8 +785,8 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180730214132-a0f8a16cb08c/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/internal/catalogmetadata/client/client.go b/internal/catalogmetadata/client/client.go index 4b75e6291..7daddaaec 100644 --- a/internal/catalogmetadata/client/client.go +++ b/internal/catalogmetadata/client/client.go @@ -12,8 +12,9 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - catalogd "github.com/operator-framework/catalogd/api/v1" "github.com/operator-framework/operator-registry/alpha/declcfg" + + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" ) const ( diff --git a/internal/catalogmetadata/client/client_test.go b/internal/catalogmetadata/client/client_test.go index 16adb94a0..45228684a 100644 --- a/internal/catalogmetadata/client/client_test.go +++ b/internal/catalogmetadata/client/client_test.go @@ -14,9 +14,9 @@ import ( "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - catalogd "github.com/operator-framework/catalogd/api/v1" "github.com/operator-framework/operator-registry/alpha/declcfg" + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" catalogClient "github.com/operator-framework/operator-controller/internal/catalogmetadata/client" ) diff --git a/internal/controllers/clustercatalog_controller.go b/internal/controllers/clustercatalog_controller.go index f326b4578..2ee78694f 100644 --- a/internal/controllers/clustercatalog_controller.go +++ b/internal/controllers/clustercatalog_controller.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - catalogd "github.com/operator-framework/catalogd/api/v1" + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" ) type CatalogCache interface { diff --git a/internal/controllers/clustercatalog_controller_test.go b/internal/controllers/clustercatalog_controller_test.go index 2bc1cb2bb..92cbbe269 100644 --- a/internal/controllers/clustercatalog_controller_test.go +++ b/internal/controllers/clustercatalog_controller_test.go @@ -14,8 +14,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" - catalogd "github.com/operator-framework/catalogd/api/v1" - + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" "github.com/operator-framework/operator-controller/internal/controllers" "github.com/operator-framework/operator-controller/internal/scheme" ) diff --git a/internal/controllers/clusterextension_controller.go b/internal/controllers/clusterextension_controller.go index f77511539..66c61de6f 100644 --- a/internal/controllers/clusterextension_controller.go +++ b/internal/controllers/clusterextension_controller.go @@ -45,11 +45,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/operator-framework/api/pkg/operators/v1alpha1" - catalogd "github.com/operator-framework/catalogd/api/v1" helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client" "github.com/operator-framework/operator-registry/alpha/declcfg" ocv1 "github.com/operator-framework/operator-controller/api/v1" + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" "github.com/operator-framework/operator-controller/internal/bundleutil" "github.com/operator-framework/operator-controller/internal/conditionsets" "github.com/operator-framework/operator-controller/internal/contentmanager" diff --git a/internal/resolve/catalog.go b/internal/resolve/catalog.go index 944744c5f..ea7cf6e32 100644 --- a/internal/resolve/catalog.go +++ b/internal/resolve/catalog.go @@ -15,10 +15,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - catalogd "github.com/operator-framework/catalogd/api/v1" "github.com/operator-framework/operator-registry/alpha/declcfg" ocv1 "github.com/operator-framework/operator-controller/api/v1" + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" "github.com/operator-framework/operator-controller/internal/bundleutil" "github.com/operator-framework/operator-controller/internal/catalogmetadata/compare" "github.com/operator-framework/operator-controller/internal/catalogmetadata/filter" diff --git a/internal/resolve/catalog_test.go b/internal/resolve/catalog_test.go index 83eeba9b0..1054a1fcd 100644 --- a/internal/resolve/catalog_test.go +++ b/internal/resolve/catalog_test.go @@ -16,11 +16,11 @@ import ( "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" - catalogd "github.com/operator-framework/catalogd/api/v1" "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/alpha/property" ocv1 "github.com/operator-framework/operator-controller/api/v1" + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" "github.com/operator-framework/operator-controller/internal/features" ) diff --git a/internal/scheme/scheme.go b/internal/scheme/scheme.go index a5fae6298..fecdacf08 100644 --- a/internal/scheme/scheme.go +++ b/internal/scheme/scheme.go @@ -7,9 +7,8 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" - catalogd "github.com/operator-framework/catalogd/api/v1" - ocv1 "github.com/operator-framework/operator-controller/api/v1" + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" ) var Scheme = runtime.NewScheme() diff --git a/scripts/install.tpl.sh b/scripts/install.tpl.sh index 1d8811c73..705a9d88b 100644 --- a/scripts/install.tpl.sh +++ b/scripts/install.tpl.sh @@ -2,26 +2,19 @@ set -euo pipefail IFS=$'\n\t' -operator_controller_manifest=$MANIFEST +olmv1_manifest=$MANIFEST -if [[ -z "$operator_controller_manifest" ]]; then +if [[ -z "$olmv1_manifest" ]]; then echo "Error: Missing required MANIFEST variable" exit 1 fi -catalogd_version=$CATALOGD_VERSION +default_catalogs_manifest="./catalogd/config/base/default/clustercatalogs/default-catalogs.yaml" cert_mgr_version=$CERT_MGR_VERSION install_default_catalogs=$INSTALL_DEFAULT_CATALOGS -if [[ -z "$catalogd_version" || -z "$cert_mgr_version" ]]; then - err="Error: Missing component version(s) for: " - if [[ -z "$catalogd_version" ]]; then - err+="catalogd " - fi - if [[ -z "$cert_mgr_version" ]]; then - err+="cert-manager " - fi - echo "$err" +if [[ -z "$cert_mgr_version" ]]; then + echo "Error: Missing CERT_MGR_VERSION variable" exit 1 fi @@ -76,15 +69,18 @@ kubectl_wait "cert-manager" "deployment/cert-manager" "60s" kubectl_wait_for_query "mutatingwebhookconfigurations/cert-manager-webhook" '{.webhooks[0].clientConfig.caBundle}' 60 5 kubectl_wait_for_query "validatingwebhookconfigurations/cert-manager-webhook" '{.webhooks[0].clientConfig.caBundle}' 60 5 -kubectl apply -f "https://github.com/operator-framework/catalogd/releases/download/${catalogd_version}/catalogd.yaml" +kubectl apply -f "${olmv1_manifest}" # Wait for the rollout, and then wait for the deployment to be Available kubectl_wait_rollout "olmv1-system" "deployment/catalogd-controller-manager" "60s" kubectl_wait "olmv1-system" "deployment/catalogd-controller-manager" "60s" +kubectl_wait "olmv1-system" "deployment/operator-controller-controller-manager" "60s" if [[ "${install_default_catalogs}" != "false" ]]; then - kubectl apply -f "https://github.com/operator-framework/catalogd/releases/download/${catalogd_version}/default-catalogs.yaml" + if [[ ! -f "$default_catalogs_manifest" ]]; then + echo "Error: Missing required default catalogs manifest file at $default_catalogs_manifest" + exit 1 + fi + + kubectl apply -f "${default_catalogs_manifest}" kubectl wait --for=condition=Serving "clustercatalog/operatorhubio" --timeout="60s" fi - -kubectl apply -f "${operator_controller_manifest}" -kubectl_wait "olmv1-system" "deployment/operator-controller-controller-manager" "60s" diff --git a/test/e2e/cluster_extension_install_test.go b/test/e2e/cluster_extension_install_test.go index 6d137fb1a..74cf3b3da 100644 --- a/test/e2e/cluster_extension_install_test.go +++ b/test/e2e/cluster_extension_install_test.go @@ -28,9 +28,8 @@ import ( "k8s.io/utils/env" "sigs.k8s.io/controller-runtime/pkg/client" - catalogd "github.com/operator-framework/catalogd/api/v1" - ocv1 "github.com/operator-framework/operator-controller/api/v1" + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" ) const ( diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index df6d3fdd9..e65fd5e5d 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -13,8 +13,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - catalogd "github.com/operator-framework/catalogd/api/v1" - + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" "github.com/operator-framework/operator-controller/internal/scheme" ) diff --git a/test/extension-developer-e2e/extension_developer_test.go b/test/extension-developer-e2e/extension_developer_test.go index 5edaa910c..5f160617c 100644 --- a/test/extension-developer-e2e/extension_developer_test.go +++ b/test/extension-developer-e2e/extension_developer_test.go @@ -18,9 +18,8 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - catalogd "github.com/operator-framework/catalogd/api/v1" - ocv1 "github.com/operator-framework/operator-controller/api/v1" + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" ) func TestExtensionDeveloper(t *testing.T) { diff --git a/test/upgrade-e2e/post_upgrade_test.go b/test/upgrade-e2e/post_upgrade_test.go index e361f8814..547a7142a 100644 --- a/test/upgrade-e2e/post_upgrade_test.go +++ b/test/upgrade-e2e/post_upgrade_test.go @@ -18,9 +18,8 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - catalogd "github.com/operator-framework/catalogd/api/v1" - ocv1 "github.com/operator-framework/operator-controller/api/v1" + catalogd "github.com/operator-framework/operator-controller/catalogd/api/v1" ) func TestClusterExtensionAfterOLMUpgrade(t *testing.T) {